Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / content / xml / document / src / nsXMLFragmentContentSink.cpp
blob8030c40d8619cacc62792fbae885373784585763
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Steve Swanson <steve.swanson@mackichan.com>
19 * Portions created by the Initial Developer are Copyright (C) 2004
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Blake Kaplan <mrbkap@gmail.com>
24 * Robert Sayre <sayrer@gmail.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
39 #include "nsCOMPtr.h"
40 #include "nsXMLContentSink.h"
41 #include "nsIFragmentContentSink.h"
42 #include "nsIXMLContentSink.h"
43 #include "nsContentSink.h"
44 #include "nsIExpatSink.h"
45 #include "nsIParser.h"
46 #include "nsIDocument.h"
47 #include "nsIDOMDocumentFragment.h"
48 #include "nsIContent.h"
49 #include "nsGkAtoms.h"
50 #include "nsINodeInfo.h"
51 #include "nsNodeInfoManager.h"
52 #include "nsContentCreatorFunctions.h"
53 #include "nsDOMError.h"
54 #include "nsIConsoleService.h"
55 #include "nsIScriptError.h"
56 #include "nsServiceManagerUtils.h"
57 #include "nsContentUtils.h"
58 #include "nsIScriptSecurityManager.h"
59 #include "nsNetUtil.h"
60 #include "nsTHashtable.h"
61 #include "nsHashKeys.h"
62 #include "nsTArray.h"
63 #include "nsCycleCollectionParticipant.h"
65 class nsXMLFragmentContentSink : public nsXMLContentSink,
66 public nsIFragmentContentSink
68 public:
69 nsXMLFragmentContentSink(PRBool aAllContent = PR_FALSE);
70 virtual ~nsXMLFragmentContentSink();
72 NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
74 // nsISupports
75 NS_DECL_ISUPPORTS_INHERITED
76 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsXMLFragmentContentSink,
77 nsXMLContentSink)
79 // nsIExpatSink
80 NS_IMETHOD HandleDoctypeDecl(const nsAString & aSubset,
81 const nsAString & aName,
82 const nsAString & aSystemId,
83 const nsAString & aPublicId,
84 nsISupports* aCatalogData);
85 NS_IMETHOD HandleProcessingInstruction(const PRUnichar *aTarget,
86 const PRUnichar *aData);
87 NS_IMETHOD HandleXMLDeclaration(const PRUnichar *aVersion,
88 const PRUnichar *aEncoding,
89 PRInt32 aStandalone);
90 NS_IMETHOD ReportError(const PRUnichar* aErrorText,
91 const PRUnichar* aSourceText,
92 nsIScriptError *aError,
93 PRBool *_retval);
95 // nsIContentSink
96 NS_IMETHOD WillBuildModel(void);
97 NS_IMETHOD DidBuildModel();
98 NS_IMETHOD SetDocumentCharset(nsACString& aCharset);
99 virtual nsISupports *GetTarget();
100 NS_IMETHOD DidProcessATokenImpl();
102 // nsIXMLContentSink
104 // nsIFragmentContentSink
105 NS_IMETHOD GetFragment(PRBool aWillOwnFragment,
106 nsIDOMDocumentFragment** aFragment);
107 NS_IMETHOD SetTargetDocument(nsIDocument* aDocument);
108 NS_IMETHOD WillBuildContent();
109 NS_IMETHOD DidBuildContent();
110 NS_IMETHOD IgnoreFirstContainer();
112 protected:
113 virtual PRBool SetDocElement(PRInt32 aNameSpaceID,
114 nsIAtom *aTagName,
115 nsIContent *aContent);
116 virtual nsresult CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
117 nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
118 nsIContent** aResult, PRBool* aAppendContent,
119 PRBool aFromParser);
120 virtual nsresult CloseElement(nsIContent* aContent);
122 virtual void MaybeStartLayout(PRBool aIgnorePendingSheets);
124 // nsContentSink overrides
125 virtual nsresult ProcessStyleLink(nsIContent* aElement,
126 const nsSubstring& aHref,
127 PRBool aAlternate,
128 const nsSubstring& aTitle,
129 const nsSubstring& aType,
130 const nsSubstring& aMedia);
131 nsresult LoadXSLStyleSheet(nsIURI* aUrl);
132 void StartLayout();
134 nsCOMPtr<nsIDocument> mTargetDocument;
135 // the fragment
136 nsCOMPtr<nsIContent> mRoot;
137 PRPackedBool mParseError;
139 // if FALSE, take content inside endnote tag
140 PRPackedBool mAllContent;
143 static nsresult
144 NewXMLFragmentContentSinkHelper(PRBool aAllContent, nsIFragmentContentSink** aResult)
146 nsXMLFragmentContentSink* it = new nsXMLFragmentContentSink(aAllContent);
147 if (!it) {
148 return NS_ERROR_OUT_OF_MEMORY;
151 NS_ADDREF(*aResult = it);
153 return NS_OK;
156 nsresult
157 NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aResult)
159 return NewXMLFragmentContentSinkHelper(PR_TRUE, aResult);
162 nsresult
163 NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aResult)
165 return NewXMLFragmentContentSinkHelper(PR_FALSE, aResult);
168 nsXMLFragmentContentSink::nsXMLFragmentContentSink(PRBool aAllContent)
169 : mParseError(PR_FALSE), mAllContent(aAllContent)
173 nsXMLFragmentContentSink::~nsXMLFragmentContentSink()
177 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsXMLFragmentContentSink)
178 NS_INTERFACE_MAP_ENTRY(nsIFragmentContentSink)
179 NS_INTERFACE_MAP_END_INHERITING(nsXMLContentSink)
181 NS_IMPL_ADDREF_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
182 NS_IMPL_RELEASE_INHERITED(nsXMLFragmentContentSink, nsXMLContentSink)
184 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLFragmentContentSink)
186 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXMLFragmentContentSink,
187 nsXMLContentSink)
188 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTargetDocument)
189 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
190 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
192 NS_IMETHODIMP
193 nsXMLFragmentContentSink::WillBuildModel(void)
195 if (mRoot) {
196 return NS_OK;
199 mState = eXMLContentSinkState_InDocumentElement;
201 NS_ASSERTION(mTargetDocument, "Need a document!");
203 nsCOMPtr<nsIDOMDocumentFragment> frag;
204 nsresult rv = NS_NewDocumentFragment(getter_AddRefs(frag), mNodeInfoManager);
205 NS_ENSURE_SUCCESS(rv, rv);
207 mRoot = do_QueryInterface(frag);
209 if (mAllContent) {
210 // Preload content stack because we know all content goes in the fragment
211 PushContent(mRoot);
214 return rv;
217 NS_IMETHODIMP
218 nsXMLFragmentContentSink::DidBuildModel()
220 if (mAllContent) {
221 PopContent(); // remove mRoot pushed above
224 nsCOMPtr<nsIParser> kungFuDeathGrip(mParser);
226 // Drop our reference to the parser to get rid of a circular
227 // reference.
228 mParser = nsnull;
230 return NS_OK;
233 NS_IMETHODIMP
234 nsXMLFragmentContentSink::SetDocumentCharset(nsACString& aCharset)
236 NS_NOTREACHED("fragments shouldn't set charset");
237 return NS_OK;
240 nsISupports *
241 nsXMLFragmentContentSink::GetTarget()
243 return mTargetDocument;
246 ////////////////////////////////////////////////////////////////////////
248 PRBool
249 nsXMLFragmentContentSink::SetDocElement(PRInt32 aNameSpaceID,
250 nsIAtom* aTagName,
251 nsIContent *aContent)
253 // this is a fragment, not a document
254 return PR_FALSE;
257 nsresult
258 nsXMLFragmentContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
259 nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
260 nsIContent** aResult, PRBool* aAppendContent,
261 PRBool aFromParser)
263 // Claim to not be coming from parser, since we don't do any of the
264 // fancy CloseElement stuff.
265 nsresult rv = nsXMLContentSink::CreateElement(aAtts, aAttsCount,
266 aNodeInfo, aLineNumber,
267 aResult, aAppendContent,
268 PR_FALSE);
270 // When we aren't grabbing all of the content we, never open a doc
271 // element, we run into trouble on the first element, so we don't append,
272 // and simply push this onto the content stack.
273 if (!mAllContent && mContentStack.Length() == 0) {
274 *aAppendContent = PR_FALSE;
277 return rv;
280 nsresult
281 nsXMLFragmentContentSink::CloseElement(nsIContent* aContent)
283 // don't do fancy stuff in nsXMLContentSink
284 return NS_OK;
287 void
288 nsXMLFragmentContentSink::MaybeStartLayout(PRBool aIgnorePendingSheets)
290 return;
293 ////////////////////////////////////////////////////////////////////////
295 NS_IMETHODIMP
296 nsXMLFragmentContentSink::HandleDoctypeDecl(const nsAString & aSubset,
297 const nsAString & aName,
298 const nsAString & aSystemId,
299 const nsAString & aPublicId,
300 nsISupports* aCatalogData)
302 NS_NOTREACHED("fragments shouldn't have doctype declarations");
304 return NS_OK;
307 NS_IMETHODIMP
308 nsXMLFragmentContentSink::HandleProcessingInstruction(const PRUnichar *aTarget,
309 const PRUnichar *aData)
311 FlushText();
313 nsresult result = NS_OK;
314 const nsDependentString target(aTarget);
315 const nsDependentString data(aData);
317 nsCOMPtr<nsIContent> node;
319 result = NS_NewXMLProcessingInstruction(getter_AddRefs(node),
320 mNodeInfoManager, target, data);
321 if (NS_SUCCEEDED(result)) {
322 // no special processing here. that should happen when the fragment moves into the document
323 result = AddContentAsLeaf(node);
325 return result;
328 NS_IMETHODIMP
329 nsXMLFragmentContentSink::HandleXMLDeclaration(const PRUnichar *aVersion,
330 const PRUnichar *aEncoding,
331 PRInt32 aStandalone)
333 NS_NOTREACHED("fragments shouldn't have XML declarations");
334 return NS_OK;
337 NS_IMETHODIMP
338 nsXMLFragmentContentSink::ReportError(const PRUnichar* aErrorText,
339 const PRUnichar* aSourceText,
340 nsIScriptError *aError,
341 PRBool *_retval)
343 NS_PRECONDITION(aError && aSourceText && aErrorText, "Check arguments!!!");
345 // The expat driver should report the error.
346 *_retval = PR_TRUE;
348 mParseError = PR_TRUE;
350 #ifdef DEBUG
351 // Report the error to stderr.
352 fprintf(stderr,
353 "\n%s\n%s\n\n",
354 NS_LossyConvertUTF16toASCII(aErrorText).get(),
355 NS_LossyConvertUTF16toASCII(aSourceText).get());
356 #endif
358 // The following code is similar to the cleanup in nsXMLContentSink::ReportError()
359 mState = eXMLContentSinkState_InProlog;
361 // Clear the current content
362 nsCOMPtr<nsIDOMNode> node(do_QueryInterface(mRoot));
363 if (node) {
364 for (;;) {
365 nsCOMPtr<nsIDOMNode> child, dummy;
366 node->GetLastChild(getter_AddRefs(child));
367 if (!child)
368 break;
369 node->RemoveChild(child, getter_AddRefs(dummy));
373 // Clear any buffered-up text we have. It's enough to set the length to 0.
374 // The buffer itself is allocated when we're created and deleted in our
375 // destructor, so don't mess with it.
376 mTextLength = 0;
378 return NS_OK;
381 nsresult
382 nsXMLFragmentContentSink::ProcessStyleLink(nsIContent* aElement,
383 const nsSubstring& aHref,
384 PRBool aAlternate,
385 const nsSubstring& aTitle,
386 const nsSubstring& aType,
387 const nsSubstring& aMedia)
389 // don't process until moved to document
390 return NS_OK;
393 nsresult
394 nsXMLFragmentContentSink::LoadXSLStyleSheet(nsIURI* aUrl)
396 NS_NOTREACHED("fragments shouldn't have XSL style sheets");
397 return NS_ERROR_UNEXPECTED;
400 void
401 nsXMLFragmentContentSink::StartLayout()
403 NS_NOTREACHED("fragments shouldn't layout");
406 ////////////////////////////////////////////////////////////////////////
408 NS_IMETHODIMP
409 nsXMLFragmentContentSink::GetFragment(PRBool aWillOwnFragment,
410 nsIDOMDocumentFragment** aFragment)
412 *aFragment = nsnull;
413 if (mParseError) {
414 //XXX PARSE_ERR from DOM3 Load and Save would be more appropriate
415 return NS_ERROR_DOM_SYNTAX_ERR;
416 } else if (mRoot) {
417 nsresult rv = CallQueryInterface(mRoot, aFragment);
418 if (NS_SUCCEEDED(rv) && aWillOwnFragment) {
419 mRoot = nsnull;
421 return rv;
422 } else {
423 return NS_OK;
427 NS_IMETHODIMP
428 nsXMLFragmentContentSink::SetTargetDocument(nsIDocument* aTargetDocument)
430 NS_ENSURE_ARG_POINTER(aTargetDocument);
432 mTargetDocument = aTargetDocument;
433 mNodeInfoManager = aTargetDocument->NodeInfoManager();
435 return NS_OK;
438 NS_IMETHODIMP
439 nsXMLFragmentContentSink::WillBuildContent()
441 // If we're taking all of the content, then we've already pushed mRoot
442 // onto the content stack, otherwise, start here.
443 if (!mAllContent) {
444 PushContent(mRoot);
447 return NS_OK;
450 NS_IMETHODIMP
451 nsXMLFragmentContentSink::DidBuildContent()
453 // If we're taking all of the content, then this is handled in DidBuildModel
454 if (!mAllContent) {
455 // Note: we need to FlushText() here because if we don't, we might not get
456 // an end element to do it for us, so make sure.
457 if (!mParseError) {
458 FlushText();
460 PopContent();
463 return NS_OK;
466 NS_IMETHODIMP
467 nsXMLFragmentContentSink::DidProcessATokenImpl()
469 return NS_OK;
472 NS_IMETHODIMP
473 nsXMLFragmentContentSink::IgnoreFirstContainer()
475 NS_NOTREACHED("XML isn't as broken as HTML");
476 return NS_ERROR_FAILURE;
480 // nsXHTMLParanoidFragmentSink
482 // Find the whitelist of allowed elements and attributes in
483 // nsContentSink.h We share it with nsHTMLParanoidFragmentSink
485 class nsXHTMLParanoidFragmentSink : public nsXMLFragmentContentSink
487 public:
488 nsXHTMLParanoidFragmentSink();
490 static nsresult Init();
491 static void Cleanup();
493 // nsISupports
494 NS_DECL_ISUPPORTS_INHERITED
496 // nsXMLContentSink
497 nsresult AddAttributes(const PRUnichar** aNode, nsIContent* aContent);
499 // nsIExpatSink
500 NS_IMETHOD HandleStartElement(const PRUnichar *aName,
501 const PRUnichar **aAtts,
502 PRUint32 aAttsCount, PRInt32 aIndex,
503 PRUint32 aLineNumber);
505 NS_IMETHOD HandleEndElement(const PRUnichar *aName);
507 NS_IMETHOD HandleComment(const PRUnichar *aName);
509 NS_IMETHOD HandleProcessingInstruction(const PRUnichar *aTarget,
510 const PRUnichar *aData);
512 NS_IMETHOD HandleCDataSection(const PRUnichar *aData,
513 PRUint32 aLength);
515 NS_IMETHOD HandleCharacterData(const PRUnichar *aData,
516 PRUint32 aLength);
517 protected:
518 PRUint32 mSkipLevel; // used when we descend into <style> or <script>
519 // Use nsTHashTable as a hash set for our whitelists
520 static nsTHashtable<nsISupportsHashKey>* sAllowedTags;
521 static nsTHashtable<nsISupportsHashKey>* sAllowedAttributes;
524 nsTHashtable<nsISupportsHashKey>* nsXHTMLParanoidFragmentSink::sAllowedTags;
525 nsTHashtable<nsISupportsHashKey>* nsXHTMLParanoidFragmentSink::sAllowedAttributes;
527 nsXHTMLParanoidFragmentSink::nsXHTMLParanoidFragmentSink():
528 nsXMLFragmentContentSink(PR_FALSE), mSkipLevel(0)
532 nsresult
533 nsXHTMLParanoidFragmentSink::Init()
535 nsresult rv = NS_ERROR_FAILURE;
537 if (sAllowedTags) {
538 return NS_OK;
541 sAllowedTags = new nsTHashtable<nsISupportsHashKey>();
542 if (sAllowedTags) {
543 rv = sAllowedTags->Init(80);
544 for (PRUint32 i = 0; kDefaultAllowedTags[i] && NS_SUCCEEDED(rv); i++) {
545 if (!sAllowedTags->PutEntry(*kDefaultAllowedTags[i])) {
546 rv = NS_ERROR_OUT_OF_MEMORY;
551 sAllowedAttributes = new nsTHashtable<nsISupportsHashKey>();
552 if (sAllowedAttributes && NS_SUCCEEDED(rv)) {
553 rv = sAllowedAttributes->Init(80);
554 for (PRUint32 i = 0;
555 kDefaultAllowedAttributes[i] && NS_SUCCEEDED(rv); i++) {
556 if (!sAllowedAttributes->PutEntry(*kDefaultAllowedAttributes[i])) {
557 rv = NS_ERROR_OUT_OF_MEMORY;
562 if (NS_FAILED(rv)) {
563 NS_WARNING("Failed to populate whitelist hash sets");
564 Cleanup();
567 return rv;
570 void
571 nsXHTMLParanoidFragmentSink::Cleanup()
573 if (sAllowedTags) {
574 delete sAllowedTags;
575 sAllowedTags = nsnull;
578 if (sAllowedAttributes) {
579 delete sAllowedAttributes;
580 sAllowedAttributes = nsnull;
584 nsresult
585 NS_NewXHTMLParanoidFragmentSink(nsIFragmentContentSink** aResult)
587 nsXHTMLParanoidFragmentSink* it = new nsXHTMLParanoidFragmentSink();
588 if (!it) {
589 return NS_ERROR_OUT_OF_MEMORY;
591 nsresult rv = nsXHTMLParanoidFragmentSink::Init();
592 NS_ENSURE_SUCCESS(rv, rv);
593 NS_ADDREF(*aResult = it);
595 return NS_OK;
598 void
599 NS_XHTMLParanoidFragmentSinkShutdown()
601 nsXHTMLParanoidFragmentSink::Cleanup();
604 NS_IMPL_ISUPPORTS_INHERITED0(nsXHTMLParanoidFragmentSink,
605 nsXMLFragmentContentSink)
607 nsresult
608 nsXHTMLParanoidFragmentSink::AddAttributes(const PRUnichar** aAtts,
609 nsIContent* aContent)
611 nsresult rv;
613 // use this to check for safe URIs in the few attributes that allow them
614 nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
615 nsCOMPtr<nsIURI> baseURI;
616 PRUint32 flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
618 // scrub URI attributes that point at dangerous content
619 // We have to do this here, because this is where we have a base URI,
620 // but we can't do all the scrubbing here, because other parts of the
621 // code get the attributes before this method is called.
622 nsTArray<const PRUnichar *> allowedAttrs;
623 PRInt32 nameSpaceID;
624 nsCOMPtr<nsIAtom> prefix, localName;
625 nsCOMPtr<nsINodeInfo> nodeInfo;
626 while (*aAtts) {
627 nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
628 getter_AddRefs(localName), &nameSpaceID);
629 nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID);
630 NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
631 // check the attributes we allow that contain URIs
632 if (IsAttrURI(nodeInfo->NameAtom())) {
633 if (!aAtts[1])
634 rv = NS_ERROR_FAILURE;
635 if (!baseURI)
636 baseURI = aContent->GetBaseURI();
637 nsCOMPtr<nsIURI> attrURI;
638 rv = NS_NewURI(getter_AddRefs(attrURI), nsDependentString(aAtts[1]),
639 nsnull, baseURI);
640 if (NS_SUCCEEDED(rv)) {
641 rv = secMan->CheckLoadURIWithPrincipal(mTargetDocument->NodePrincipal(),
642 attrURI, flags);
646 if (NS_SUCCEEDED(rv)) {
647 allowedAttrs.AppendElement(aAtts[0]);
648 allowedAttrs.AppendElement(aAtts[1]);
651 aAtts += 2;
653 allowedAttrs.AppendElement((const PRUnichar*) nsnull);
655 return nsXMLFragmentContentSink::AddAttributes(allowedAttrs.Elements(),
656 aContent);
659 NS_IMETHODIMP
660 nsXHTMLParanoidFragmentSink::HandleStartElement(const PRUnichar *aName,
661 const PRUnichar **aAtts,
662 PRUint32 aAttsCount,
663 PRInt32 aIndex,
664 PRUint32 aLineNumber)
666 nsresult rv;
667 PRInt32 nameSpaceID;
668 nsCOMPtr<nsIAtom> prefix, localName;
669 nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
670 getter_AddRefs(localName), &nameSpaceID);
672 // If the element is not in the XHTML namespace, bounce it
673 if (nameSpaceID != kNameSpaceID_XHTML)
674 return NS_OK;
676 nsCOMPtr<nsINodeInfo> nodeInfo;
677 nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID);
678 NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
680 // bounce it if it's not on the whitelist or we're inside
681 // <script> or <style>
682 nsCOMPtr<nsIAtom> name = nodeInfo->NameAtom();
683 if (mSkipLevel != 0 ||
684 name == nsGkAtoms::script ||
685 name == nsGkAtoms::style) {
686 ++mSkipLevel; // track this so we don't spew script text
687 return NS_OK;
690 if (!sAllowedTags || !sAllowedTags->GetEntry(name))
691 return NS_OK;
693 // It's an allowed element, so let's scrub the attributes
694 nsTArray<const PRUnichar *> allowedAttrs;
695 for (PRUint32 i = 0; i < aAttsCount; i += 2) {
696 nsContentUtils::SplitExpatName(aAtts[i], getter_AddRefs(prefix),
697 getter_AddRefs(localName), &nameSpaceID);
698 nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID);
699 NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
701 name = nodeInfo->NameAtom();
702 // Add if it's xmlns, xml: or on the HTML whitelist
703 if (nameSpaceID == kNameSpaceID_XMLNS ||
704 nameSpaceID == kNameSpaceID_XML ||
705 (sAllowedAttributes && sAllowedAttributes->GetEntry(name))) {
706 allowedAttrs.AppendElement(aAtts[i]);
707 allowedAttrs.AppendElement(aAtts[i + 1]);
710 allowedAttrs.AppendElement((const PRUnichar*) nsnull);
711 return
712 nsXMLFragmentContentSink::HandleStartElement(aName,
713 allowedAttrs.Elements(),
714 allowedAttrs.Length() - 1,
715 aIndex,
716 aLineNumber);
719 NS_IMETHODIMP
720 nsXHTMLParanoidFragmentSink::HandleEndElement(const PRUnichar *aName)
722 PRInt32 nameSpaceID;
723 nsCOMPtr<nsIAtom> prefix, localName;
724 nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
725 getter_AddRefs(localName), &nameSpaceID);
727 // If the element is not in the XHTML namespace, bounce it
728 if (nameSpaceID != kNameSpaceID_XHTML) {
729 return NS_OK;
732 nsCOMPtr<nsINodeInfo> nodeInfo;
733 nodeInfo = mNodeInfoManager->GetNodeInfo(localName, prefix, nameSpaceID);
734 NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY);
736 nsCOMPtr<nsIAtom> name = nodeInfo->NameAtom();
737 if (mSkipLevel != 0) {
738 --mSkipLevel;
739 return NS_OK;
742 if (!sAllowedTags || !sAllowedTags->GetEntry(name)) {
743 return NS_OK;
746 return nsXMLFragmentContentSink::HandleEndElement(aName);
749 NS_IMETHODIMP
750 nsXHTMLParanoidFragmentSink::
751 HandleProcessingInstruction(const PRUnichar *aTarget,
752 const PRUnichar *aData)
754 // We don't do PIs
755 return NS_OK;
758 NS_IMETHODIMP
759 nsXHTMLParanoidFragmentSink::HandleComment(const PRUnichar *aName)
761 // We don't do comments
762 return NS_OK;
765 // We pass all character data through, unless we're inside <script>
766 NS_IMETHODIMP
767 nsXHTMLParanoidFragmentSink::HandleCDataSection(const PRUnichar *aData,
768 PRUint32 aLength)
770 if (mSkipLevel != 0) {
771 return NS_OK;
774 return nsXMLFragmentContentSink::HandleCDataSection(aData, aLength);
777 NS_IMETHODIMP
778 nsXHTMLParanoidFragmentSink::HandleCharacterData(const PRUnichar *aData,
779 PRUint32 aLength)
781 if (mSkipLevel != 0) {
782 return NS_OK;
785 return nsXMLFragmentContentSink::HandleCharacterData(aData, aLength);