1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 et tw=78: */
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/. */
8 #include "nsXMLContentSink.h"
10 #include "nsIDocument.h"
11 #include "nsIDOMDocument.h"
12 #include "nsIDOMDocumentType.h"
13 #include "nsIContent.h"
15 #include "nsNetUtil.h"
16 #include "nsIDocShell.h"
17 #include "nsIStyleSheetLinkingElement.h"
18 #include "nsIDOMComment.h"
19 #include "nsIDOMCDATASection.h"
20 #include "DocumentType.h"
21 #include "nsHTMLParts.h"
23 #include "mozilla/CSSStyleSheet.h"
24 #include "mozilla/css/Loader.h"
25 #include "nsGkAtoms.h"
26 #include "nsContentUtils.h"
27 #include "nsIScriptContext.h"
28 #include "nsNameSpaceManager.h"
29 #include "nsIServiceManager.h"
30 #include "nsIScriptSecurityManager.h"
31 #include "nsIContentViewer.h"
36 #include "nsIWebNavigation.h"
37 #include "nsIScriptElement.h"
38 #include "nsScriptLoader.h"
39 #include "nsStyleLinkElement.h"
40 #include "nsReadableUtils.h"
41 #include "nsUnicharUtils.h"
42 #include "nsICookieService.h"
43 #include "nsIPrompt.h"
44 #include "nsIChannel.h"
45 #include "nsIPrincipal.h"
46 #include "nsXMLPrettyPrinter.h"
47 #include "nsNodeInfoManager.h"
48 #include "nsContentCreatorFunctions.h"
49 #include "nsIContentPolicy.h"
50 #include "nsContentPolicyUtils.h"
52 #include "nsIDOMProcessingInstruction.h"
53 #include "nsNodeUtils.h"
54 #include "nsIScriptGlobalObject.h"
55 #include "nsIHTMLDocument.h"
56 #include "mozAutoDocUpdate.h"
57 #include "nsMimeTypes.h"
58 #include "nsHtml5SVGLoadDispatcher.h"
59 #include "nsTextNode.h"
60 #include "mozilla/dom/CDATASection.h"
61 #include "mozilla/dom/Comment.h"
62 #include "mozilla/dom/Element.h"
63 #include "mozilla/dom/HTMLTemplateElement.h"
64 #include "mozilla/dom/ProcessingInstruction.h"
66 using namespace mozilla
;
67 using namespace mozilla::dom
;
70 // 1) what's not allowed - We need to figure out which HTML tags
71 // (prefixed with a HTML namespace qualifier) are explicitly not
73 // 2) factoring code with nsHTMLContentSink - There's some amount of
74 // common code between this and the HTML content sink. This will
75 // increase as we support more and more HTML elements. How can code
76 // from the code be factored?
79 NS_NewXMLContentSink(nsIXMLContentSink
** aResult
,
82 nsISupports
* aContainer
,
85 NS_PRECONDITION(nullptr != aResult
, "null ptr");
86 if (nullptr == aResult
) {
87 return NS_ERROR_NULL_POINTER
;
89 nsXMLContentSink
* it
= new nsXMLContentSink();
91 nsCOMPtr
<nsIXMLContentSink
> kungFuDeathGrip
= it
;
92 nsresult rv
= it
->Init(aDoc
, aURI
, aContainer
, aChannel
);
93 NS_ENSURE_SUCCESS(rv
, rv
);
95 return CallQueryInterface(it
, aResult
);
98 nsXMLContentSink::nsXMLContentSink()
99 : mConstrainSize(true),
100 mPrettyPrintXML(true)
104 nsXMLContentSink::~nsXMLContentSink()
107 PR_Free(mText
); // Doesn't null out, unlike PR_FREEIF
112 nsXMLContentSink::Init(nsIDocument
* aDoc
,
114 nsISupports
* aContainer
,
115 nsIChannel
* aChannel
)
117 nsresult rv
= nsContentSink::Init(aDoc
, aURI
, aContainer
, aChannel
);
118 NS_ENSURE_SUCCESS(rv
, rv
);
120 aDoc
->AddObserver(this);
121 mIsDocumentObserver
= true;
124 mPrettyPrintXML
= false;
127 mState
= eXMLContentSinkState_InProlog
;
128 mDocElement
= nullptr;
133 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLContentSink
)
134 NS_INTERFACE_MAP_ENTRY(nsIContentSink
)
135 NS_INTERFACE_MAP_ENTRY(nsIXMLContentSink
)
136 NS_INTERFACE_MAP_ENTRY(nsIExpatSink
)
137 NS_INTERFACE_MAP_ENTRY(nsITransformObserver
)
138 NS_INTERFACE_MAP_END_INHERITING(nsContentSink
)
140 NS_IMPL_ADDREF_INHERITED(nsXMLContentSink
, nsContentSink
)
141 NS_IMPL_RELEASE_INHERITED(nsXMLContentSink
, nsContentSink
)
143 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLContentSink
)
145 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLContentSink
,
147 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentHead
)
148 NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocElement
)
149 for (uint32_t i
= 0, count
= tmp
->mContentStack
.Length(); i
< count
; i
++) {
150 const StackNode
& node
= tmp
->mContentStack
.ElementAt(i
);
151 cb
.NoteXPCOMChild(node
.mContent
);
153 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
157 nsXMLContentSink::WillParse(void)
159 return WillParseImpl();
163 nsXMLContentSink::WillBuildModel(nsDTDMode aDTDMode
)
165 WillBuildModelImpl();
167 // Notify document that the load is beginning
168 mDocument
->BeginLoad();
170 // Check for correct load-command for maybe prettyprinting
171 if (mPrettyPrintXML
) {
172 nsAutoCString command
;
173 GetParser()->GetCommand(command
);
174 if (!command
.EqualsLiteral("view")) {
175 mPrettyPrintXML
= false;
183 nsXMLContentSink::CanStillPrettyPrint()
185 return mPrettyPrintXML
&&
186 (!mPrettyPrintHasFactoredElements
|| mPrettyPrintHasSpecialRoot
);
190 nsXMLContentSink::MaybePrettyPrint()
192 if (!CanStillPrettyPrint()) {
193 mPrettyPrintXML
= false;
198 // stop observing in order to avoid crashing when replacing content
199 mDocument
->RemoveObserver(this);
200 mIsDocumentObserver
= false;
202 // Reenable the CSSLoader so that the prettyprinting stylesheets can load
204 mCSSLoader
->SetEnabled(true);
207 nsRefPtr
<nsXMLPrettyPrinter
> printer
;
208 nsresult rv
= NS_NewXMLPrettyPrinter(getter_AddRefs(printer
));
209 NS_ENSURE_SUCCESS(rv
, rv
);
211 bool isPrettyPrinting
;
212 rv
= printer
->PrettyPrint(mDocument
, &isPrettyPrinting
);
213 NS_ENSURE_SUCCESS(rv
, rv
);
215 mPrettyPrinting
= isPrettyPrinting
;
220 CheckXSLTParamPI(nsIDOMProcessingInstruction
* aPi
,
221 nsIDocumentTransformer
* aProcessor
,
222 nsIDocument
* aDocument
)
224 nsAutoString target
, data
;
225 aPi
->GetTarget(target
);
227 // Check for namespace declarations
228 if (target
.EqualsLiteral("xslt-param-namespace")) {
230 nsAutoString prefix
, namespaceAttr
;
231 nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::prefix
,
233 if (!prefix
.IsEmpty() &&
234 nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::_namespace
,
236 aProcessor
->AddXSLTParamNamespace(prefix
, namespaceAttr
);
240 // Check for actual parameters
241 else if (target
.EqualsLiteral("xslt-param")) {
243 nsAutoString name
, namespaceAttr
, select
, value
;
244 nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::name
,
246 nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::_namespace
,
248 if (!nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::select
, select
)) {
249 select
.SetIsVoid(true);
251 if (!nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::value
, value
)) {
252 value
.SetIsVoid(true);
254 if (!name
.IsEmpty()) {
255 nsCOMPtr
<nsIDOMNode
> doc
= do_QueryInterface(aDocument
);
256 aProcessor
->AddXSLTParam(name
, namespaceAttr
, select
, value
, doc
);
262 nsXMLContentSink::DidBuildModel(bool aTerminated
)
265 // If mParser is null, this parse has already been terminated and must
266 // not been terminated again. However, nsDocument may still think that
267 // the parse has not been terminated and call back into here in the case
268 // where the XML parser has finished but the XSLT transform associated
269 // with the document has not.
273 DidBuildModelImpl(aTerminated
);
275 if (mXSLTProcessor
) {
276 // stop observing in order to avoid crashing when replacing content
277 mDocument
->RemoveObserver(this);
278 mIsDocumentObserver
= false;
280 // Check for xslt-param and xslt-param-namespace PIs
281 for (nsIContent
* child
= mDocument
->GetFirstChild();
283 child
= child
->GetNextSibling()) {
284 if (child
->IsNodeOfType(nsINode::ePROCESSING_INSTRUCTION
)) {
285 nsCOMPtr
<nsIDOMProcessingInstruction
> pi
= do_QueryInterface(child
);
286 CheckXSLTParamPI(pi
, mXSLTProcessor
, mDocument
);
288 else if (child
->IsElement()) {
289 // Only honor PIs in the prolog
294 nsCOMPtr
<nsIDOMDocument
> currentDOMDoc(do_QueryInterface(mDocument
));
295 mXSLTProcessor
->SetSourceContentModel(currentDOMDoc
);
296 // Since the processor now holds a reference to us we drop our reference
297 // to it to avoid owning cycles
298 mXSLTProcessor
= nullptr;
301 // Kick off layout for non-XSLT transformed documents.
303 // Check if we want to prettyprint
306 bool startLayout
= true;
308 if (mPrettyPrinting
) {
309 NS_ASSERTION(!mPendingSheetCount
, "Shouldn't have pending sheets here!");
311 // We're pretty-printing now. See whether we should wait up on
313 if (mDocument
->CSSLoader()->HasPendingLoads() &&
314 NS_SUCCEEDED(mDocument
->CSSLoader()->AddObserver(this))) {
315 // wait for those sheets to load
326 mDocument
->RemoveObserver(this);
327 mIsDocumentObserver
= false;
329 mDocument
->EndLoad();
332 DropParserAndPerfHint();
338 nsXMLContentSink::OnDocumentCreated(nsIDocument
* aResultDocument
)
340 NS_ENSURE_ARG(aResultDocument
);
342 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(aResultDocument
);
344 htmlDoc
->SetDocWriteDisabled(true);
347 nsCOMPtr
<nsIContentViewer
> contentViewer
;
348 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
350 return contentViewer
->SetDocumentInternal(aResultDocument
, true);
356 nsXMLContentSink::OnTransformDone(nsresult aResult
,
357 nsIDocument
* aResultDocument
)
359 NS_ASSERTION(NS_FAILED(aResult
) || aResultDocument
,
360 "Don't notify about transform success without a document.");
362 nsCOMPtr
<nsIDOMDocument
> domDoc
= do_QueryInterface(aResultDocument
);
364 nsCOMPtr
<nsIContentViewer
> contentViewer
;
365 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
367 if (NS_FAILED(aResult
) && contentViewer
) {
370 aResultDocument
->SetMayStartLayout(false);
371 // We have an error document.
372 contentViewer
->SetDOMDocument(domDoc
);
375 // We don't have an error document, display the
376 // untransformed source document.
377 nsCOMPtr
<nsIDOMDocument
> document
= do_QueryInterface(mDocument
);
378 contentViewer
->SetDOMDocument(document
);
382 nsCOMPtr
<nsIDocument
> originalDocument
= mDocument
;
383 if (NS_SUCCEEDED(aResult
) || aResultDocument
) {
384 // Transform succeeded or it failed and we have an error
385 // document to display.
386 mDocument
= aResultDocument
;
387 nsCOMPtr
<nsIHTMLDocument
> htmlDoc
= do_QueryInterface(mDocument
);
389 htmlDoc
->SetDocWriteDisabled(false);
393 // Notify document observers that all the content has been stuck
394 // into the document.
395 // XXX do we need to notify for things like PIs? Or just the
397 nsIContent
*rootElement
= mDocument
->GetRootElement();
399 NS_ASSERTION(mDocument
->IndexOf(rootElement
) != -1,
400 "rootElement not in doc?");
401 mDocument
->BeginUpdate(UPDATE_CONTENT_MODEL
);
402 nsNodeUtils::ContentInserted(mDocument
, rootElement
,
403 mDocument
->IndexOf(rootElement
));
404 mDocument
->EndUpdate(UPDATE_CONTENT_MODEL
);
407 // Start the layout process
412 originalDocument
->EndLoad();
418 nsXMLContentSink::StyleSheetLoaded(CSSStyleSheet
* aSheet
,
422 if (!mPrettyPrinting
) {
423 return nsContentSink::StyleSheetLoaded(aSheet
, aWasAlternate
, aStatus
);
426 if (!mDocument
->CSSLoader()->HasPendingLoads()) {
427 mDocument
->CSSLoader()->RemoveObserver(this);
436 nsXMLContentSink::WillInterrupt(void)
438 return WillInterruptImpl();
442 nsXMLContentSink::WillResume(void)
444 return WillResumeImpl();
448 nsXMLContentSink::SetParser(nsParserBase
* aParser
)
450 NS_PRECONDITION(aParser
, "Should have a parser here!");
456 nsXMLContentSink::CreateElement(const char16_t
** aAtts
, uint32_t aAttsCount
,
457 mozilla::dom::NodeInfo
* aNodeInfo
, uint32_t aLineNumber
,
458 nsIContent
** aResult
, bool* aAppendContent
,
459 FromParser aFromParser
)
461 NS_ASSERTION(aNodeInfo
, "can't create element without nodeinfo");
464 *aAppendContent
= true;
467 nsRefPtr
<mozilla::dom::NodeInfo
> ni
= aNodeInfo
;
468 nsRefPtr
<Element
> content
;
469 rv
= NS_NewElement(getter_AddRefs(content
), ni
.forget(), aFromParser
);
470 NS_ENSURE_SUCCESS(rv
, rv
);
472 if (aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XHTML
)
473 || aNodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_SVG
)
475 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(content
);
476 sele
->SetScriptLineNumber(aLineNumber
);
477 sele
->SetCreatorParser(GetParser());
478 mConstrainSize
= false;
481 // XHTML needs some special attention
482 if (aNodeInfo
->NamespaceEquals(kNameSpaceID_XHTML
)) {
483 mPrettyPrintHasFactoredElements
= true;
486 // If we care, find out if we just used a special factory.
487 if (!mPrettyPrintHasFactoredElements
&& !mPrettyPrintHasSpecialRoot
&&
489 mPrettyPrintHasFactoredElements
=
490 nsContentUtils::NameSpaceManager()->
491 HasElementCreator(aNodeInfo
->NamespaceID());
494 if (!aNodeInfo
->NamespaceEquals(kNameSpaceID_SVG
)) {
495 content
.forget(aResult
);
501 if (aNodeInfo
->Equals(nsGkAtoms::link
, kNameSpaceID_XHTML
) ||
502 aNodeInfo
->Equals(nsGkAtoms::style
, kNameSpaceID_XHTML
) ||
503 aNodeInfo
->Equals(nsGkAtoms::style
, kNameSpaceID_SVG
)) {
504 nsCOMPtr
<nsIStyleSheetLinkingElement
> ssle(do_QueryInterface(content
));
506 ssle
->InitStyleLinkElement(false);
508 ssle
->SetEnableUpdates(false);
510 if (!aNodeInfo
->Equals(nsGkAtoms::link
, kNameSpaceID_XHTML
)) {
511 ssle
->SetLineNumber(aFromParser
? aLineNumber
: 0);
516 content
.forget(aResult
);
523 nsXMLContentSink::CloseElement(nsIContent
* aContent
)
525 NS_ASSERTION(aContent
, "missing element to close");
527 mozilla::dom::NodeInfo
*nodeInfo
= aContent
->NodeInfo();
529 // Some HTML nodes need DoneAddingChildren() called to initialize
530 // properly (eg form state restoration).
531 if ((nodeInfo
->NamespaceID() == kNameSpaceID_XHTML
&&
532 (nodeInfo
->NameAtom() == nsGkAtoms::select
||
533 nodeInfo
->NameAtom() == nsGkAtoms::textarea
||
534 nodeInfo
->NameAtom() == nsGkAtoms::video
||
535 nodeInfo
->NameAtom() == nsGkAtoms::audio
||
536 nodeInfo
->NameAtom() == nsGkAtoms::object
||
537 nodeInfo
->NameAtom() == nsGkAtoms::applet
))
538 || nodeInfo
->NameAtom() == nsGkAtoms::title
540 aContent
->DoneAddingChildren(HaveNotifiedForCurrentContent());
543 if (IsMonolithicContainer(nodeInfo
)) {
544 mInMonolithicContainer
--;
547 if (!nodeInfo
->NamespaceEquals(kNameSpaceID_XHTML
) &&
548 !nodeInfo
->NamespaceEquals(kNameSpaceID_SVG
)) {
552 if (nodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_XHTML
)
553 || nodeInfo
->Equals(nsGkAtoms::script
, kNameSpaceID_SVG
)
555 mConstrainSize
= true;
556 nsCOMPtr
<nsIScriptElement
> sele
= do_QueryInterface(aContent
);
558 if (mPreventScriptExecution
) {
559 sele
->PreventExecution();
563 // Always check the clock in nsContentSink right after a script
566 // Now tell the script that it's ready to go. This may execute the script
567 // or return true, or neither if the script doesn't need executing.
568 bool block
= sele
->AttemptToExecute();
570 // If the parser got blocked, make sure to return the appropriate rv.
571 // I'm not sure if this is actually needed or not.
572 if (mParser
&& !mParser
->IsParserEnabled()) {
573 // XXX The HTML sink doesn't call BlockParser here, why do we?
574 GetParser()->BlockParser();
578 return block
? NS_ERROR_HTMLPARSER_BLOCK
: NS_OK
;
582 if (nodeInfo
->Equals(nsGkAtoms::meta
, kNameSpaceID_XHTML
) &&
583 // Need to check here to make sure this meta tag does not set
584 // mPrettyPrintXML to false when we have a special root!
585 (!mPrettyPrintXML
|| !mPrettyPrintHasSpecialRoot
)) {
586 rv
= ProcessMETATag(aContent
);
588 else if (nodeInfo
->Equals(nsGkAtoms::link
, kNameSpaceID_XHTML
) ||
589 nodeInfo
->Equals(nsGkAtoms::style
, kNameSpaceID_XHTML
) ||
590 nodeInfo
->Equals(nsGkAtoms::style
, kNameSpaceID_SVG
)) {
591 nsCOMPtr
<nsIStyleSheetLinkingElement
> ssle(do_QueryInterface(aContent
));
593 ssle
->SetEnableUpdates(true);
596 rv
= ssle
->UpdateStyleSheet(mRunsToCompletion
? nullptr : this,
599 if (NS_SUCCEEDED(rv
) && willNotify
&& !isAlternate
&& !mRunsToCompletion
) {
600 ++mPendingSheetCount
;
601 mScriptLoader
->AddExecuteBlocker();
604 // Look for <link rel="dns-prefetch" href="hostname">
605 // and look for <link rel="next" href="hostname"> like in HTML sink
606 if (nodeInfo
->Equals(nsGkAtoms::link
, kNameSpaceID_XHTML
)) {
608 aContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::rel
, relVal
);
609 if (!relVal
.IsEmpty()) {
611 nsStyleLinkElement::ParseLinkTypes(relVal
, aContent
->NodePrincipal());
612 bool hasPrefetch
= linkTypes
& nsStyleLinkElement::ePREFETCH
;
613 if (hasPrefetch
|| (linkTypes
& nsStyleLinkElement::eNEXT
)) {
614 nsAutoString hrefVal
;
615 aContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::href
, hrefVal
);
616 if (!hrefVal
.IsEmpty()) {
617 PrefetchHref(hrefVal
, aContent
, hasPrefetch
);
620 if (linkTypes
& nsStyleLinkElement::eDNS_PREFETCH
) {
621 nsAutoString hrefVal
;
622 aContent
->GetAttr(kNameSpaceID_None
, nsGkAtoms::href
, hrefVal
);
623 if (!hrefVal
.IsEmpty()) {
624 PrefetchDNS(hrefVal
);
635 nsXMLContentSink::AddContentAsLeaf(nsIContent
*aContent
)
637 nsresult result
= NS_OK
;
639 if ((eXMLContentSinkState_InProlog
== mState
) ||
640 (eXMLContentSinkState_InEpilog
== mState
)) {
641 NS_ASSERTION(mDocument
, "Fragments have no prolog or epilog");
642 mDocument
->AppendChildTo(aContent
, false);
645 nsCOMPtr
<nsIContent
> parent
= GetCurrentContent();
648 result
= parent
->AppendChildTo(aContent
, false);
654 // Create an XML parser and an XSL content sink and start parsing
655 // the XSL stylesheet located at the given URI.
657 nsXMLContentSink::LoadXSLStyleSheet(nsIURI
* aUrl
)
659 nsCOMPtr
<nsIDocumentTransformer
> processor
=
660 do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt");
662 // No XSLT processor available, continue normal document loading
666 processor
->Init(mDocument
->NodePrincipal());
667 processor
->SetTransformObserver(this);
669 nsCOMPtr
<nsILoadGroup
> loadGroup
= mDocument
->GetDocumentLoadGroup();
671 return NS_ERROR_FAILURE
;
674 if (NS_SUCCEEDED(processor
->LoadStyleSheet(aUrl
, loadGroup
))) {
675 mXSLTProcessor
.swap(processor
);
678 // Intentionally ignore errors here, we should continue loading the
679 // XML document whether we're able to load the XSLT stylesheet or
686 nsXMLContentSink::ProcessStyleLink(nsIContent
* aElement
,
687 const nsSubstring
& aHref
,
689 const nsSubstring
& aTitle
,
690 const nsSubstring
& aType
,
691 const nsSubstring
& aMedia
)
694 mPrettyPrintXML
= false;
698 GetParser()->GetCommand(cmd
);
699 if (cmd
.EqualsASCII(kLoadAsData
))
700 return NS_OK
; // Do not load stylesheets when loading as data
702 NS_ConvertUTF16toUTF8
type(aType
);
703 if (type
.EqualsIgnoreCase(TEXT_XSL
) ||
704 type
.EqualsIgnoreCase(APPLICATION_XSLT_XML
) ||
705 type
.EqualsIgnoreCase(TEXT_XML
) ||
706 type
.EqualsIgnoreCase(APPLICATION_XML
)) {
708 // don't load alternate XSLT
711 // LoadXSLStyleSheet needs a mDocShell.
715 nsCOMPtr
<nsIURI
> url
;
716 rv
= NS_NewURI(getter_AddRefs(url
), aHref
, nullptr,
717 mDocument
->GetDocBaseURI());
718 NS_ENSURE_SUCCESS(rv
, rv
);
721 nsIScriptSecurityManager
*secMan
= nsContentUtils::GetSecurityManager();
723 CheckLoadURIWithPrincipal(mDocument
->NodePrincipal(), url
,
724 nsIScriptSecurityManager::ALLOW_CHROME
);
725 NS_ENSURE_SUCCESS(rv
, NS_OK
);
727 // Do content policy check
728 int16_t decision
= nsIContentPolicy::ACCEPT
;
729 rv
= NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_XSLT
,
731 mDocument
->NodePrincipal(),
736 nsContentUtils::GetContentPolicy(),
737 nsContentUtils::GetSecurityManager());
739 NS_ENSURE_SUCCESS(rv
, rv
);
741 if (NS_CP_REJECTED(decision
)) {
745 return LoadXSLStyleSheet(url
);
748 // Let nsContentSink deal with css.
749 rv
= nsContentSink::ProcessStyleLink(aElement
, aHref
, aAlternate
,
750 aTitle
, aType
, aMedia
);
752 // nsContentSink::ProcessStyleLink handles the bookkeeping here wrt
759 nsXMLContentSink::SetDocumentCharset(nsACString
& aCharset
)
762 mDocument
->SetDocumentCharacterSet(aCharset
);
769 nsXMLContentSink::GetTarget()
775 nsXMLContentSink::IsScriptExecuting()
777 return IsScriptExecutingImpl();
781 nsXMLContentSink::FlushText(bool aReleaseTextNode
)
785 if (mTextLength
!= 0) {
787 if ((mLastTextNodeSize
+ mTextLength
) > mTextSize
&& !mXSLTProcessor
) {
788 mLastTextNodeSize
= 0;
789 mLastTextNode
= nullptr;
790 FlushText(aReleaseTextNode
);
792 bool notify
= HaveNotifiedForCurrentContent();
793 // We could probably always increase mInNotification here since
794 // if AppendText doesn't notify it shouldn't trigger evil code.
795 // But just in case it does, we don't want to mask any notifications.
799 rv
= mLastTextNode
->AppendText(mText
, mTextLength
, notify
);
804 mLastTextNodeSize
+= mTextLength
;
808 nsRefPtr
<nsTextNode
> textContent
= new nsTextNode(mNodeInfoManager
);
810 mLastTextNode
= textContent
;
812 // Set the text in the text node
813 textContent
->SetText(mText
, mTextLength
, false);
814 mLastTextNodeSize
+= mTextLength
;
817 // Add text to its parent
818 rv
= AddContentAsLeaf(textContent
);
822 if (aReleaseTextNode
) {
823 mLastTextNodeSize
= 0;
824 mLastTextNode
= nullptr;
831 nsXMLContentSink::GetCurrentContent()
833 if (mContentStack
.Length() == 0) {
836 return GetCurrentStackNode()->mContent
;
840 nsXMLContentSink::GetCurrentStackNode()
842 int32_t count
= mContentStack
.Length();
843 return count
!= 0 ? &mContentStack
[count
-1] : nullptr;
848 nsXMLContentSink::PushContent(nsIContent
*aContent
)
850 NS_PRECONDITION(aContent
, "Null content being pushed!");
851 StackNode
*sn
= mContentStack
.AppendElement();
852 NS_ENSURE_TRUE(sn
, NS_ERROR_OUT_OF_MEMORY
);
854 nsIContent
* contentToPush
= aContent
;
856 // When an XML parser would append a node to a template element, it
857 // must instead append it to the template element's template contents.
858 if (contentToPush
->IsHTML(nsGkAtoms::_template
)) {
859 HTMLTemplateElement
* templateElement
=
860 static_cast<HTMLTemplateElement
*>(contentToPush
);
861 contentToPush
= templateElement
->Content();
864 sn
->mContent
= contentToPush
;
870 nsXMLContentSink::PopContent()
872 int32_t count
= mContentStack
.Length();
875 NS_WARNING("Popping empty stack");
879 mContentStack
.RemoveElementAt(count
- 1);
883 nsXMLContentSink::HaveNotifiedForCurrentContent() const
885 uint32_t stackLength
= mContentStack
.Length();
887 const StackNode
& stackNode
= mContentStack
[stackLength
- 1];
888 nsIContent
* parent
= stackNode
.mContent
;
889 return stackNode
.mNumFlushed
== parent
->GetChildCount();
895 nsXMLContentSink::MaybeStartLayout(bool aIgnorePendingSheets
)
897 // XXXbz if aIgnorePendingSheets is true, what should we do when
898 // mXSLTProcessor or CanStillPrettyPrint()?
899 if (mLayoutStarted
|| mXSLTProcessor
|| CanStillPrettyPrint()) {
902 StartLayout(aIgnorePendingSheets
);
905 ////////////////////////////////////////////////////////////////////////
908 nsXMLContentSink::SetDocElement(int32_t aNameSpaceID
,
910 nsIContent
*aContent
)
915 // check for root elements that needs special handling for
917 if ((aNameSpaceID
== kNameSpaceID_XBL
&&
918 aTagName
== nsGkAtoms::bindings
) ||
919 (aNameSpaceID
== kNameSpaceID_XSLT
&&
920 (aTagName
== nsGkAtoms::stylesheet
||
921 aTagName
== nsGkAtoms::transform
))) {
922 mPrettyPrintHasSpecialRoot
= true;
923 if (mPrettyPrintXML
) {
924 // In this case, disable script execution, stylesheet
925 // loading, and auto XLinks since we plan to prettyprint.
926 mDocument
->ScriptLoader()->SetEnabled(false);
928 mCSSLoader
->SetEnabled(false);
933 mDocElement
= aContent
;
934 nsresult rv
= mDocument
->AppendChildTo(mDocElement
, NotifyForDocElement());
936 // If we return false here, the caller will bail out because it won't
937 // find a parent content node to append to, which is fine.
941 if (aTagName
== nsGkAtoms::html
&&
942 aNameSpaceID
== kNameSpaceID_XHTML
) {
943 ProcessOfflineManifest(aContent
);
950 nsXMLContentSink::HandleStartElement(const char16_t
*aName
,
951 const char16_t
**aAtts
,
953 uint32_t aLineNumber
)
955 return HandleStartElement(aName
, aAtts
, aAttsCount
, aLineNumber
,
960 nsXMLContentSink::HandleStartElement(const char16_t
*aName
,
961 const char16_t
**aAtts
,
963 uint32_t aLineNumber
,
966 NS_PRECONDITION(aAttsCount
% 2 == 0, "incorrect aAttsCount");
967 // Adjust aAttsCount so it's the actual number of attributes
970 nsresult result
= NS_OK
;
971 bool appendContent
= true;
972 nsCOMPtr
<nsIContent
> content
;
974 // XXX Hopefully the parser will flag this before we get
975 // here. If we're in the epilog, there should be no
977 PR_ASSERT(eXMLContentSinkState_InEpilog
!= mState
);
982 mState
= eXMLContentSinkState_InDocumentElement
;
985 nsCOMPtr
<nsIAtom
> prefix
, localName
;
986 nsContentUtils::SplitExpatName(aName
, getter_AddRefs(prefix
),
987 getter_AddRefs(localName
), &nameSpaceID
);
989 if (!OnOpenContainer(aAtts
, aAttsCount
, nameSpaceID
, localName
, aLineNumber
)) {
993 nsRefPtr
<mozilla::dom::NodeInfo
> nodeInfo
;
994 nodeInfo
= mNodeInfoManager
->GetNodeInfo(localName
, prefix
, nameSpaceID
,
995 nsIDOMNode::ELEMENT_NODE
);
997 result
= CreateElement(aAtts
, aAttsCount
, nodeInfo
, aLineNumber
,
998 getter_AddRefs(content
), &appendContent
,
999 FROM_PARSER_NETWORK
);
1000 NS_ENSURE_SUCCESS(result
, result
);
1002 // Have to do this before we push the new content on the stack... and have to
1003 // do that before we set attributes, call BindToTree, etc. Ideally we'd push
1004 // on the stack inside CreateElement (which is effectively what the HTML sink
1005 // does), but that's hard with all the subclass overrides going on.
1006 nsCOMPtr
<nsIContent
> parent
= GetCurrentContent();
1008 result
= PushContent(content
);
1009 NS_ENSURE_SUCCESS(result
, result
);
1011 // Set the attributes on the new content element
1012 result
= AddAttributes(aAtts
, content
);
1014 if (NS_OK
== result
) {
1015 // Store the element
1016 if (!SetDocElement(nameSpaceID
, localName
, content
) && appendContent
) {
1017 NS_ENSURE_TRUE(parent
, NS_ERROR_UNEXPECTED
);
1019 parent
->AppendChildTo(content
, false);
1023 // Some HTML nodes need DoneCreatingElement() called to initialize
1024 // properly (eg form state restoration).
1025 if (nodeInfo
->NamespaceID() == kNameSpaceID_XHTML
) {
1026 if (nodeInfo
->NameAtom() == nsGkAtoms::input
||
1027 nodeInfo
->NameAtom() == nsGkAtoms::button
||
1028 nodeInfo
->NameAtom() == nsGkAtoms::menuitem
||
1029 nodeInfo
->NameAtom() == nsGkAtoms::audio
||
1030 nodeInfo
->NameAtom() == nsGkAtoms::video
) {
1031 content
->DoneCreatingElement();
1032 } else if (nodeInfo
->NameAtom() == nsGkAtoms::head
&& !mCurrentHead
) {
1033 mCurrentHead
= content
;
1037 if (IsMonolithicContainer(nodeInfo
)) {
1038 mInMonolithicContainer
++;
1041 if (content
!= mDocElement
&& !mCurrentHead
) {
1042 // This isn't the root and we're not inside an XHTML <head>.
1043 // Might need to start layout
1044 MaybeStartLayout(false);
1047 if (content
== mDocElement
) {
1048 NotifyDocElementCreated(mDocument
);
1051 return aInterruptable
&& NS_SUCCEEDED(result
) ? DidProcessATokenImpl() :
1056 nsXMLContentSink::HandleEndElement(const char16_t
*aName
)
1058 return HandleEndElement(aName
, true);
1062 nsXMLContentSink::HandleEndElement(const char16_t
*aName
,
1063 bool aInterruptable
)
1065 nsresult result
= NS_OK
;
1067 // XXX Hopefully the parser will flag this before we get
1068 // here. If we're in the prolog or epilog, there should be
1069 // no close tags for elements.
1070 PR_ASSERT(eXMLContentSinkState_InDocumentElement
== mState
);
1074 StackNode
* sn
= GetCurrentStackNode();
1076 return NS_ERROR_UNEXPECTED
;
1079 nsCOMPtr
<nsIContent
> content
;
1080 sn
->mContent
.swap(content
);
1081 uint32_t numFlushed
= sn
->mNumFlushed
;
1084 NS_ASSERTION(content
, "failed to pop content");
1086 // Check that we're closing the right thing
1087 nsCOMPtr
<nsIAtom
> debugNameSpacePrefix
, debugTagAtom
;
1088 int32_t debugNameSpaceID
;
1089 nsContentUtils::SplitExpatName(aName
, getter_AddRefs(debugNameSpacePrefix
),
1090 getter_AddRefs(debugTagAtom
),
1092 // Check if we are closing a template element because template
1093 // elements do not get pushed on the stack, the template
1094 // element content is pushed instead.
1095 bool isTemplateElement
= debugTagAtom
== nsGkAtoms::_template
&&
1096 debugNameSpaceID
== kNameSpaceID_XHTML
;
1097 NS_ASSERTION(content
->NodeInfo()->Equals(debugTagAtom
, debugNameSpaceID
) ||
1098 isTemplateElement
, "Wrong element being closed");
1101 result
= CloseElement(content
);
1103 if (mCurrentHead
== content
) {
1104 mCurrentHead
= nullptr;
1107 if (mDocElement
== content
) {
1108 // XXXbz for roots that don't want to be appended on open, we
1109 // probably need to deal here.... (and stop appending them on open).
1110 mState
= eXMLContentSinkState_InEpilog
;
1112 // We might have had no occasion to start layout yet. Do so now.
1113 MaybeStartLayout(false);
1116 int32_t stackLen
= mContentStack
.Length();
1117 if (mNotifyLevel
>= stackLen
) {
1118 if (numFlushed
< content
->GetChildCount()) {
1119 NotifyAppend(content
, numFlushed
);
1121 mNotifyLevel
= stackLen
- 1;
1125 if (content
->IsSVG(nsGkAtoms::svg
)) {
1127 nsCOMPtr
<nsIRunnable
> event
= new nsHtml5SVGLoadDispatcher(content
);
1128 if (NS_FAILED(NS_DispatchToMainThread(event
))) {
1129 NS_WARNING("failed to dispatch svg load dispatcher");
1133 return aInterruptable
&& NS_SUCCEEDED(result
) ? DidProcessATokenImpl() :
1138 nsXMLContentSink::HandleComment(const char16_t
*aName
)
1142 nsRefPtr
<Comment
> comment
= new Comment(mNodeInfoManager
);
1143 comment
->SetText(nsDependentString(aName
), false);
1144 nsresult rv
= AddContentAsLeaf(comment
);
1147 return NS_SUCCEEDED(rv
) ? DidProcessATokenImpl() : rv
;
1151 nsXMLContentSink::HandleCDataSection(const char16_t
*aData
,
1154 // XSLT doesn't differentiate between text and cdata and wants adjacent
1155 // textnodes merged, so add as text.
1156 if (mXSLTProcessor
) {
1157 return AddText(aData
, aLength
);
1162 nsRefPtr
<CDATASection
> cdata
= new CDATASection(mNodeInfoManager
);
1163 cdata
->SetText(aData
, aLength
, false);
1164 nsresult rv
= AddContentAsLeaf(cdata
);
1167 return NS_SUCCEEDED(rv
) ? DidProcessATokenImpl() : rv
;
1171 nsXMLContentSink::HandleDoctypeDecl(const nsAString
& aSubset
,
1172 const nsAString
& aName
,
1173 const nsAString
& aSystemId
,
1174 const nsAString
& aPublicId
,
1175 nsISupports
* aCatalogData
)
1179 nsresult rv
= NS_OK
;
1181 NS_ASSERTION(mDocument
, "Shouldn't get here from a document fragment");
1183 nsCOMPtr
<nsIAtom
> name
= do_GetAtom(aName
);
1184 NS_ENSURE_TRUE(name
, NS_ERROR_OUT_OF_MEMORY
);
1186 // Create a new doctype node
1187 nsCOMPtr
<nsIDOMDocumentType
> docType
;
1188 rv
= NS_NewDOMDocumentType(getter_AddRefs(docType
), mNodeInfoManager
,
1189 name
, aPublicId
, aSystemId
, aSubset
);
1190 if (NS_FAILED(rv
) || !docType
) {
1194 MOZ_ASSERT(!aCatalogData
, "Need to add back support for catalog style "
1197 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(docType
);
1198 NS_ASSERTION(content
, "doctype isn't content?");
1200 rv
= mDocument
->AppendChildTo(content
, false);
1202 return NS_SUCCEEDED(rv
) ? DidProcessATokenImpl() : rv
;
1206 nsXMLContentSink::HandleCharacterData(const char16_t
*aData
,
1209 return HandleCharacterData(aData
, aLength
, true);
1213 nsXMLContentSink::HandleCharacterData(const char16_t
*aData
, uint32_t aLength
,
1214 bool aInterruptable
)
1216 nsresult rv
= NS_OK
;
1217 if (aData
&& mState
!= eXMLContentSinkState_InProlog
&&
1218 mState
!= eXMLContentSinkState_InEpilog
) {
1219 rv
= AddText(aData
, aLength
);
1221 return aInterruptable
&& NS_SUCCEEDED(rv
) ? DidProcessATokenImpl() : rv
;
1225 nsXMLContentSink::HandleProcessingInstruction(const char16_t
*aTarget
,
1226 const char16_t
*aData
)
1230 const nsDependentString
target(aTarget
);
1231 const nsDependentString
data(aData
);
1233 nsCOMPtr
<nsIContent
> node
=
1234 NS_NewXMLProcessingInstruction(mNodeInfoManager
, target
, data
);
1236 nsCOMPtr
<nsIStyleSheetLinkingElement
> ssle(do_QueryInterface(node
));
1238 ssle
->InitStyleLinkElement(false);
1239 ssle
->SetEnableUpdates(false);
1240 mPrettyPrintXML
= false;
1243 nsresult rv
= AddContentAsLeaf(node
);
1244 NS_ENSURE_SUCCESS(rv
, rv
);
1248 // This is an xml-stylesheet processing instruction... but it might not be
1249 // a CSS one if the type is set to something else.
1250 ssle
->SetEnableUpdates(true);
1253 rv
= ssle
->UpdateStyleSheet(mRunsToCompletion
? nullptr : this,
1256 NS_ENSURE_SUCCESS(rv
, rv
);
1259 // Successfully started a stylesheet load
1260 if (!isAlternate
&& !mRunsToCompletion
) {
1261 ++mPendingSheetCount
;
1262 mScriptLoader
->AddExecuteBlocker();
1269 // If it's not a CSS stylesheet PI...
1271 nsContentUtils::GetPseudoAttributeValue(data
, nsGkAtoms::type
, type
);
1273 if (mState
!= eXMLContentSinkState_InProlog
||
1274 !target
.EqualsLiteral("xml-stylesheet") ||
1276 type
.LowerCaseEqualsLiteral("text/css")) {
1277 return DidProcessATokenImpl();
1280 nsAutoString href
, title
, media
;
1281 bool isAlternate
= false;
1283 // If there was no href, we can't do anything with this PI
1284 if (!ParsePIData(data
, href
, title
, media
, isAlternate
)) {
1285 return DidProcessATokenImpl();
1288 rv
= ProcessStyleLink(node
, href
, isAlternate
, title
, type
, media
);
1289 return NS_SUCCEEDED(rv
) ? DidProcessATokenImpl() : rv
;
1294 nsXMLContentSink::ParsePIData(const nsString
&aData
, nsString
&aHref
,
1295 nsString
&aTitle
, nsString
&aMedia
,
1298 // If there was no href, we can't do anything with this PI
1299 if (!nsContentUtils::GetPseudoAttributeValue(aData
, nsGkAtoms::href
, aHref
)) {
1303 nsContentUtils::GetPseudoAttributeValue(aData
, nsGkAtoms::title
, aTitle
);
1305 nsContentUtils::GetPseudoAttributeValue(aData
, nsGkAtoms::media
, aMedia
);
1307 nsAutoString alternate
;
1308 nsContentUtils::GetPseudoAttributeValue(aData
,
1309 nsGkAtoms::alternate
,
1312 aIsAlternate
= alternate
.EqualsLiteral("yes");
1318 nsXMLContentSink::HandleXMLDeclaration(const char16_t
*aVersion
,
1319 const char16_t
*aEncoding
,
1320 int32_t aStandalone
)
1322 mDocument
->SetXMLDeclaration(aVersion
, aEncoding
, aStandalone
);
1324 return DidProcessATokenImpl();
1328 nsXMLContentSink::ReportError(const char16_t
* aErrorText
,
1329 const char16_t
* aSourceText
,
1330 nsIScriptError
*aError
,
1333 NS_PRECONDITION(aError
&& aSourceText
&& aErrorText
, "Check arguments!!!");
1334 nsresult rv
= NS_OK
;
1336 // The expat driver should report the error. We're just cleaning up the mess.
1339 mPrettyPrintXML
= false;
1341 mState
= eXMLContentSinkState_InProlog
;
1343 // XXX need to stop scripts here -- hsivonen
1345 // stop observing in order to avoid crashing when removing content
1346 mDocument
->RemoveObserver(this);
1347 mIsDocumentObserver
= false;
1349 // Clear the current content and
1350 // prepare to set <parsererror> as the document root
1351 nsCOMPtr
<nsIDOMNode
> node(do_QueryInterface(mDocument
));
1354 nsCOMPtr
<nsIDOMNode
> child
, dummy
;
1355 node
->GetLastChild(getter_AddRefs(child
));
1358 node
->RemoveChild(child
, getter_AddRefs(dummy
));
1361 mDocElement
= nullptr;
1363 // Clear any buffered-up text we have. It's enough to set the length to 0.
1364 // The buffer itself is allocated when we're created and deleted in our
1365 // destructor, so don't mess with it.
1368 if (mXSLTProcessor
) {
1369 // Get rid of the XSLT processor.
1370 mXSLTProcessor
->CancelLoads();
1371 mXSLTProcessor
= nullptr;
1374 // release the nodes on stack
1375 mContentStack
.Clear();
1378 rv
= HandleProcessingInstruction(MOZ_UTF16("xml-stylesheet"),
1379 MOZ_UTF16("href=\"chrome://global/locale/intl.css\" type=\"text/css\""));
1380 NS_ENSURE_SUCCESS(rv
, rv
);
1382 const char16_t
* noAtts
[] = { 0, 0 };
1384 NS_NAMED_LITERAL_STRING(errorNs
,
1385 "http://www.mozilla.org/newlayout/xml/parsererror.xml");
1387 nsAutoString
parsererror(errorNs
);
1388 parsererror
.Append((char16_t
)0xFFFF);
1389 parsererror
.AppendLiteral("parsererror");
1391 rv
= HandleStartElement(parsererror
.get(), noAtts
, 0, (uint32_t)-1,
1393 NS_ENSURE_SUCCESS(rv
, rv
);
1395 rv
= HandleCharacterData(aErrorText
, NS_strlen(aErrorText
), false);
1396 NS_ENSURE_SUCCESS(rv
, rv
);
1398 nsAutoString
sourcetext(errorNs
);
1399 sourcetext
.Append((char16_t
)0xFFFF);
1400 sourcetext
.AppendLiteral("sourcetext");
1402 rv
= HandleStartElement(sourcetext
.get(), noAtts
, 0, (uint32_t)-1,
1404 NS_ENSURE_SUCCESS(rv
, rv
);
1406 rv
= HandleCharacterData(aSourceText
, NS_strlen(aSourceText
), false);
1407 NS_ENSURE_SUCCESS(rv
, rv
);
1409 rv
= HandleEndElement(sourcetext
.get(), false);
1410 NS_ENSURE_SUCCESS(rv
, rv
);
1412 rv
= HandleEndElement(parsererror
.get(), false);
1413 NS_ENSURE_SUCCESS(rv
, rv
);
1421 nsXMLContentSink::AddAttributes(const char16_t
** aAtts
,
1422 nsIContent
* aContent
)
1424 // Add tag attributes to the content attributes
1425 nsCOMPtr
<nsIAtom
> prefix
, localName
;
1427 int32_t nameSpaceID
;
1428 nsContentUtils::SplitExpatName(aAtts
[0], getter_AddRefs(prefix
),
1429 getter_AddRefs(localName
), &nameSpaceID
);
1431 // Add attribute to content
1432 aContent
->SetAttr(nameSpaceID
, localName
, prefix
,
1433 nsDependentString(aAtts
[1]), false);
1440 #define NS_ACCUMULATION_BUFFER_SIZE 4096
1443 nsXMLContentSink::AddText(const char16_t
* aText
,
1446 // Create buffer when we first need it
1447 if (0 == mTextSize
) {
1448 mText
= (char16_t
*) PR_MALLOC(sizeof(char16_t
) * NS_ACCUMULATION_BUFFER_SIZE
);
1449 if (nullptr == mText
) {
1450 return NS_ERROR_OUT_OF_MEMORY
;
1452 mTextSize
= NS_ACCUMULATION_BUFFER_SIZE
;
1455 // Copy data from string into our buffer; flush buffer when it fills up
1457 while (0 != aLength
) {
1458 int32_t amount
= mTextSize
- mTextLength
;
1460 // XSLT wants adjacent textnodes merged.
1461 if (mConstrainSize
&& !mXSLTProcessor
) {
1462 nsresult rv
= FlushText();
1467 amount
= mTextSize
- mTextLength
;
1470 mTextSize
+= aLength
;
1471 mText
= (char16_t
*) PR_REALLOC(mText
, sizeof(char16_t
) * mTextSize
);
1472 if (nullptr == mText
) {
1475 return NS_ERROR_OUT_OF_MEMORY
;
1481 if (amount
> aLength
) {
1484 memcpy(&mText
[mTextLength
], &aText
[offset
], sizeof(char16_t
) * amount
);
1485 mTextLength
+= amount
;
1494 nsXMLContentSink::FlushPendingNotifications(mozFlushType aType
)
1496 // Only flush tags if we're not doing the notification ourselves
1497 // (since we aren't reentrant)
1498 if (!mInNotification
) {
1499 if (mIsDocumentObserver
) {
1500 // Only flush if we're still a document observer (so that our child
1501 // counts should be correct).
1502 if (aType
>= Flush_ContentAndNotify
) {
1509 if (aType
>= Flush_InterruptibleLayout
) {
1510 // Make sure that layout has started so that the reflow flush
1511 // will actually happen.
1512 MaybeStartLayout(true);
1518 * NOTE!! Forked from SinkContext. Please keep in sync.
1520 * Flush all elements that have been seen so far such that
1521 * they are visible in the tree. Specifically, make sure
1522 * that they are all added to their respective parents.
1523 * Also, do notification at the top for all content that
1524 * has been newly added so that the frame tree is complete.
1527 nsXMLContentSink::FlushTags()
1529 mDeferredFlushTags
= false;
1530 bool oldBeganUpdate
= mBeganUpdate
;
1531 uint32_t oldUpdates
= mUpdatesInNotification
;
1533 mUpdatesInNotification
= 0;
1536 // Scope so we call EndUpdate before we decrease mInNotification
1537 mozAutoDocUpdate
updateBatch(mDocument
, UPDATE_CONTENT_MODEL
, true);
1538 mBeganUpdate
= true;
1540 // Don't release last text node in case we need to add to it again
1543 // Start from the base of the stack (growing downward) and do
1544 // a notification from the node that is closest to the root of
1545 // tree for any content that has been added.
1548 int32_t stackLen
= mContentStack
.Length();
1549 bool flushed
= false;
1550 uint32_t childCount
;
1551 nsIContent
* content
;
1553 for (stackPos
= 0; stackPos
< stackLen
; ++stackPos
) {
1554 content
= mContentStack
[stackPos
].mContent
;
1555 childCount
= content
->GetChildCount();
1557 if (!flushed
&& (mContentStack
[stackPos
].mNumFlushed
< childCount
)) {
1558 NotifyAppend(content
, mContentStack
[stackPos
].mNumFlushed
);
1562 mContentStack
[stackPos
].mNumFlushed
= childCount
;
1564 mNotifyLevel
= stackLen
- 1;
1568 if (mUpdatesInNotification
> 1) {
1569 UpdateChildCounts();
1572 mUpdatesInNotification
= oldUpdates
;
1573 mBeganUpdate
= oldBeganUpdate
;
1579 * NOTE!! Forked from SinkContext. Please keep in sync.
1582 nsXMLContentSink::UpdateChildCounts()
1584 // Start from the top of the stack (growing upwards) and see if any
1585 // new content has been appended. If so, we recognize that reflows
1586 // have been generated for it and we should make sure that no
1587 // further reflows occur. Note that we have to include stackPos == 0
1588 // to properly notify on kids of <html>.
1589 int32_t stackLen
= mContentStack
.Length();
1590 int32_t stackPos
= stackLen
- 1;
1591 while (stackPos
>= 0) {
1592 StackNode
& node
= mContentStack
[stackPos
];
1593 node
.mNumFlushed
= node
.mContent
->GetChildCount();
1597 mNotifyLevel
= stackLen
- 1;
1601 nsXMLContentSink::IsMonolithicContainer(mozilla::dom::NodeInfo
* aNodeInfo
)
1603 return ((aNodeInfo
->NamespaceID() == kNameSpaceID_XHTML
&&
1604 (aNodeInfo
->NameAtom() == nsGkAtoms::tr
||
1605 aNodeInfo
->NameAtom() == nsGkAtoms::select
||
1606 aNodeInfo
->NameAtom() == nsGkAtoms::object
||
1607 aNodeInfo
->NameAtom() == nsGkAtoms::applet
)) ||
1608 (aNodeInfo
->NamespaceID() == kNameSpaceID_MathML
&&
1609 (aNodeInfo
->NameAtom() == nsGkAtoms::math
))
1614 nsXMLContentSink::ContinueInterruptedParsingIfEnabled()
1616 if (mParser
&& mParser
->IsParserEnabled()) {
1617 GetParser()->ContinueInterruptedParsing();
1622 nsXMLContentSink::ContinueInterruptedParsingAsync()
1624 nsCOMPtr
<nsIRunnable
> ev
= NS_NewRunnableMethod(this,
1625 &nsXMLContentSink::ContinueInterruptedParsingIfEnabled
);
1627 NS_DispatchToCurrentThread(ev
);
1631 nsXMLContentSink::GetParser()
1633 return static_cast<nsIParser
*>(mParser
.get());