Bug 482909 part 2 - Implement an HTML/SVG/MathML sanitizer independently of parsers or serializers. r=bzbarsky.
authorHenri Sivonen <hsivonen@iki.fi>
Fri, 29 Jul 2011 14:48:04 +0300
changeset 73538 8fb752f5e1fa3fa01b206e435bc79835bcb78644
parent 73537 6e4e476f00772e57fbdb453ef61e6e753fe982fe
child 73539 c8a0de7179e0722f24eee8251f16944036971cd4
child 73561 691c76a1a4559b8acab01b8ec50ce206b3d2047f
child 73684 3773e471ce368ee13d891eafa24353ab026cd8d9
push idunknown
push userunknown
push dateunknown
reviewersbzbarsky
bugs482909
milestone8.0a1
Bug 482909 part 2 - Implement an HTML/SVG/MathML sanitizer independently of parsers or serializers. r=bzbarsky.
content/base/public/Makefile.in
content/base/public/nsContentCID.h
content/base/public/nsINode.h
content/base/public/nsTreeSanitizer.h
content/base/src/Makefile.in
content/base/src/nsContentSink.cpp
content/base/src/nsContentSink.h
content/base/src/nsContentUtils.cpp
content/base/src/nsTreeSanitizer.cpp
content/html/document/src/nsHTMLFragmentContentSink.cpp
content/xml/document/src/nsXMLFragmentContentSink.cpp
editor/libeditor/html/nsHTMLDataTransfer.cpp
editor/libeditor/html/nsHTMLEditor.h
editor/libeditor/html/tests/test_bug520189.html
layout/build/nsLayoutModule.cpp
layout/build/nsLayoutStatics.cpp
layout/generic/nsHTMLParts.h
parser/htmlparser/public/nsIFragmentContentSink.h
toolkit/components/feeds/nsScriptableUnescapeHTML.cpp
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -72,16 +72,17 @@ nsIXPathEvaluatorInternal.h \
 mozISanitizingSerializer.h \
 nsCaseTreatment.h \
 nsContentCID.h \
 nsCopySupport.h \
 nsContentCreatorFunctions.h \
 nsDOMFile.h \
 nsLineBreaker.h \
 nsReferencedElement.h \
+nsTreeSanitizer.h \
 nsXMLNameSpaceMap.h \
 nsDOMEventTargetWrapperCache.h \
 $(NULL)
 
 EXPORTS_NAMESPACES = mozilla/dom
 
 EXPORTS_mozilla/dom = \
 		Element.h \
--- a/content/base/public/nsContentCID.h
+++ b/content/base/public/nsContentCID.h
@@ -148,40 +148,24 @@
 // {d4f2b600-b5c1-11d6-b483-cc97c63e567c}
 #define NS_HTMLFRAGMENTSINK_CID \
 { 0xd4f2b600, 0xb5c1, 0x11d6, { 0xb4, 0x83, 0xcc, 0x97, 0xc6, 0x3e, 0x56, 0x7c } }
 
 // {13111d00-ce81-11d6-8082-ecf3665af67c}
 #define NS_HTMLFRAGMENTSINK2_CID \
 { 0x13111d00, 0xce81, 0x11d6, { 0x80, 0x82, 0xec, 0xf3, 0x66, 0x5a, 0xf6, 0x7c } }
 
-// {A47E9526-6E48-4574-9D6C-3164E271F74E}
-#define NS_HTMLPARANOIDFRAGMENTSINK_CID \
-{ 0xa47e9526, 0x6e48, 0x4574, { 0x9d, 0x6c, 0x31, 0x64, 0xe2, 0x71, 0xf7, 0x4e } }
-
-// {35aab9d8-db42-4c82-8aba-fad2b1d8f465}
-#define NS_HTMLPARANOIDFRAGMENTSINK2_CID \
-{ 0x35aab9d8, 0xdb42, 0x4c82, { 0x8a, 0xba, 0xfa, 0xd2, 0xb1, 0xd8, 0xf4, 0x65 } }
-
 // {4B664E54-72A2-4bbf-A5C2-66D4DC3066A0}
 #define NS_XMLFRAGMENTSINK_CID \
 { 0x4b664e54, 0x72a2, 0x4bbf, { 0xa5, 0xc2, 0x66, 0xd4, 0xdc, 0x30, 0x66, 0xa0 } }
 
 // {4DC30689-929D-425e-A709-082C6294E542}
 #define NS_XMLFRAGMENTSINK2_CID \
 { 0x4dc30689, 0x929d, 0x425e, { 0xa7, 0x9, 0x8, 0x2c, 0x62, 0x94, 0xe5, 0x42 } }
 
-// {2D78BBF0-E26C-482B-92B3-78A7B2AFC8F7}
-#define NS_XHTMLPARANOIDFRAGMENTSINK_CID  \
-{ 0x2d78bbf0, 0xe26c, 0x482b, { 0x92, 0xb3, 0x78, 0xa7, 0xb2, 0xaf, 0xc8, 0xf7} }
-
-// {921dac9c-ffd4-4b5c-9901-4015b03862e6}
-#define NS_XHTMLPARANOIDFRAGMENTSINK2_CID  \
-{ 0x921dac9c, 0xffd4, 0x4b5c, { 0x99, 0x01, 0x40, 0x15, 0xb0, 0x38, 0x62, 0xe6} }
-
 // {3986B301-097C-11d3-BF87-00105A1B0627}
 #define NS_XULPOPUPLISTENER_CID \
 { 0x3986b301, 0x97c, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
 
 // {1F5C1721-7DC3-11d3-BF87-00105A1B0627}
 #define NS_XULCONTROLLERS_CID \
 { 0x1f5c1721, 0x7dc3, 0x11d3, { 0xbf, 0x87, 0x0, 0x10, 0x5a, 0x1b, 0x6, 0x27 } }
 
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -1098,29 +1098,51 @@ public:
    * Get the next node in the pre-order tree traversal of the DOM.  If
    * aRoot is non-null, then it must be an ancestor of |this|
    * (possibly equal to |this|) and only nodes that are descendants of
    * aRoot, not including aRoot itself, will be returned.  Returns
    * null if there are no more nodes to traverse.
    */
   nsIContent* GetNextNode(const nsINode* aRoot = nsnull) const
   {
+    return GetNextNodeImpl(aRoot, PR_FALSE);
+  }
+
+  /**
+   * Get the next node in the pre-order tree traversal of the DOM but ignoring
+   * the children of this node.  If aRoot is non-null, then it must be an
+   * ancestor of |this| (possibly equal to |this|) and only nodes that are
+   * descendants of aRoot, not including aRoot itself, will be returned.
+   * Returns null if there are no more nodes to traverse.
+   */
+  nsIContent* GetNextNonChildNode(const nsINode* aRoot = nsnull) const
+  {
+    return GetNextNodeImpl(aRoot, PR_TRUE);
+  }
+
+private:
+
+  nsIContent* GetNextNodeImpl(const nsINode* aRoot,
+                              const PRBool aSkipChildren) const
+  {
     // Can't use nsContentUtils::ContentIsDescendantOf here, since we
     // can't include it here.
 #ifdef DEBUG
     if (aRoot) {
       const nsINode* cur = this;
       for (; cur; cur = cur->GetNodeParent())
         if (cur == aRoot) break;
       NS_ASSERTION(cur, "aRoot not an ancestor of |this|?");
     }
 #endif
-    nsIContent* kid = GetFirstChild();
-    if (kid) {
-      return kid;
+    if (!aSkipChildren) {
+      nsIContent* kid = GetFirstChild();
+      if (kid) {
+        return kid;
+      }
     }
     if (this == aRoot) {
       return nsnull;
     }
     const nsINode* cur = this;
     while (1) {
       nsIContent* next = cur->GetNextSibling();
       if (next) {
@@ -1130,16 +1152,18 @@ public:
       if (parent == aRoot) {
         return nsnull;
       }
       cur = parent;
     }
     NS_NOTREACHED("How did we get here?");
   }
 
+public:
+
   /**
    * Get the previous nsIContent in the pre-order tree traversal of the DOM.  If
    * aRoot is non-null, then it must be an ancestor of |this|
    * (possibly equal to |this|) and only nsIContents that are descendants of
    * aRoot, including aRoot itself, will be returned.  Returns
    * null if there are no more nsIContents to traverse.
    */
   nsIContent* GetPreviousContent(const nsINode* aRoot = nsnull) const
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsTreeSanitizer.h
@@ -0,0 +1,210 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is HTML/SVG/MathML sanitizer code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef nsTreeSanitizer_h_
+#define nsTreeSanitizer_h_
+
+#include "nsIContent.h"
+#include "mozilla/css/StyleRule.h"
+#include "nsIPrincipal.h"
+#include "mozilla/dom/Element.h"
+
+class NS_STACK_CLASS nsTreeSanitizer {
+
+  public:
+
+    /**
+     * The constructor.
+     *
+     * @param aAllowStyles Whether to allow <style> and style=""
+     * @param aAllowComments Whether to allow comment nodes
+     */
+    nsTreeSanitizer(PRBool aAllowStyles, PRBool aAllowComments);
+
+    static void InitializeStatics();
+    static void ReleaseStatics();
+
+    /**
+     * Sanitizes a disconnected DOM fragment freshly obtained from a parser.
+     * The argument must be of type nsINode::eDOCUMENT_FRAGMENT and,
+     * consequently, must not be in the document. Furthermore, the fragment
+     * must have just come from a parser so that it can't have mutation
+     * event listeners set on it.
+     */
+    void Sanitize(nsIContent* aFragment);
+
+  private:
+
+    /**
+     * Whether <style> and style="" are allowed.
+     */
+    PRBool mAllowStyles;
+
+    /**
+     * Whether comment nodes are allowed.
+     */
+    PRBool mAllowComments;
+
+    /**
+     * Queries if an element must be replaced with its children.
+     * @param aNamespace the namespace of the element the question is about
+     * @param aLocal the local name of the element the question is about
+     * @return true if the element must be replaced with its children and
+     *         false if the element is to be kept
+     */
+    PRBool MustFlatten(PRInt32 aNamespace, nsIAtom* aLocal);
+
+    /**
+     * Queries if an element including its children must be removed.
+     * @param aNamespace the namespace of the element the question is about
+     * @param aLocal the local name of the element the question is about
+     * @param aElement the element node itself for inspecting attributes
+     * @return true if the element and its children must be removed and
+     *         false if the element is to be kept
+     */
+    PRBool MustPrune(PRInt32 aNamespace,
+                     nsIAtom* aLocal,
+                     mozilla::dom::Element* aElement);
+
+    /**
+     * Checks if a given local name (for an attribute) is on the given list
+     * of URL attribute names.
+     * @param aURLs the list of URL attribute names
+     * @param aLocalName the name to search on the list
+     * @return true if aLocalName is on the aURLs list and false otherwise
+     */
+    PRBool IsURL(nsIAtom*** aURLs, nsIAtom* aLocalName);
+
+    /**
+     * Removes dangerous attributes from the element. If the style attribute
+     * is allowed, its value is sanitized. The values of URL attributes are
+     * sanitized, except src isn't sanitized when it is allowed to remain
+     * potentially dangerous.
+     *
+     * @param aElement the element whose attributes should be sanitized
+     * @param aAllowed the whitelist of permitted local names to use
+     * @param aURLs the local names of URL-valued attributes
+     * @param aAllowXLink whether XLink attributes are allowed
+     * @param aAllowStyle whether the style attribute is allowed
+     * @param aAllowDangerousSrc whether to leave the value of the src
+     *                           attribute unsanitized
+     */
+    void SanitizeAttributes(mozilla::dom::Element* aElement,
+                            nsTHashtable<nsISupportsHashKey>* aAllowed,
+                            nsIAtom*** aURLs,
+                            PRBool aAllowXLink,
+                            PRBool aAllowStyle,
+                            PRBool aAllowDangerousSrc);
+
+    /**
+     * Remove the named URL attribute from the element if the URL fails a
+     * security check.
+     *
+     * @param aElement the element whose attribute to possibly modify
+     * @param aNamespace the namespace of the URL attribute
+     * @param aLocalName the local name of the URL attribute
+     */
+    void SanitizeURL(mozilla::dom::Element* aElement,
+                     PRInt32 aNamespace,
+                     nsIAtom* aLocalName);
+
+    /**
+     * Checks a style rule for the presence of the 'binding' CSS property and
+     * removes that property from the rule and reserializes in case the
+     * property was found.
+     *
+     * @param aRule The style rule to check
+     * @param aRuleText the serialized mutated rule if the method returns true
+     * @return true if the rule was modified and false otherwise
+     */
+    PRBool SanitizeStyleRule(mozilla::css::StyleRule* aRule,
+                             nsAutoString &aRuleText);
+
+    /**
+     * Parses a style sheet and reserializes it with the 'binding' property
+     * removed if it was present.
+     *
+     * @param aOrigin the original style sheet source
+     * @param aSanitized the reserialization without 'binding'; only valid if
+     *                   this method return true
+     * @param aDocument the document the style sheet belongs to
+     * @param aBaseURI the base URI to use
+     * @return true if the 'binding' property was encountered and false
+     *              otherwise
+     */
+    PRBool SanitizeStyleSheet(const nsAString& aOriginal,
+                              nsAString& aSanitized,
+                              nsIDocument* aDocument,
+                              nsIURI* aBaseURI);
+
+    /**
+     * The whitelist of HTML elements.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sElementsHTML;
+
+    /**
+     * The whitelist of HTML attributes.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sAttributesHTML;
+
+    /**
+     * The whitelist of SVG elements.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sElementsSVG;
+
+    /**
+     * The whitelist of SVG attributes.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sAttributesSVG;
+
+    /**
+     * The whitelist of SVG elements.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sElementsMathML;
+
+    /**
+     * The whitelist of MathML attributes.
+     */
+    static nsTHashtable<nsISupportsHashKey>* sAttributesMathML;
+
+    /**
+     * Reusable null principal for URL checks.
+     */
+    static nsIPrincipal* sNullPrincipal;
+};
+
+#endif // nsTreeSanitizer_h_
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -134,16 +134,17 @@ CPPSRCS		= \
 		nsStubImageDecoderObserver.cpp \
 		nsStubMutationObserver.cpp \
 		nsStyledElement.cpp \
 		nsStyleLinkElement.cpp \
 		nsSyncLoadService.cpp \
 		nsTextFragment.cpp \
 		nsTextNode.cpp \
 		nsTraversal.cpp \
+		nsTreeSanitizer.cpp \
 		nsTreeWalker.cpp \
 		nsWebSocket.cpp \
 		nsXHTMLContentSerializer.cpp \
 		nsXMLContentSerializer.cpp \
 		nsXMLHttpRequest.cpp \
 		nsXMLNameSpaceMap.cpp \
 		Link.cpp \
 		nsFileDataProtocolHandler.cpp \
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1722,271 +1722,8 @@ nsContentSink::NotifyDocElementCreated(n
     mozilla::services::GetObserverService();
   if (observerService) {
     nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aDoc);
     observerService->
       NotifyObservers(domDoc, "document-element-inserted",
                       EmptyString().get());
   }
 }
-
-// URIs: action, href, src, longdesc, usemap, cite
-PRBool 
-IsAttrURI(nsIAtom *aName)
-{
-  return (aName == nsGkAtoms::action ||
-          aName == nsGkAtoms::href ||
-          aName == nsGkAtoms::src ||
-          aName == nsGkAtoms::longdesc ||
-          aName == nsGkAtoms::usemap ||
-          aName == nsGkAtoms::cite ||
-          aName == nsGkAtoms::background);
-}
-
-//
-// these two lists are used by the sanitizing fragment serializers
-// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
-//
-nsIAtom** const kDefaultAllowedTags [] = {
-  &nsGkAtoms::a,
-  &nsGkAtoms::abbr,
-  &nsGkAtoms::acronym,
-  &nsGkAtoms::address,
-  &nsGkAtoms::area,
-  &nsGkAtoms::article,
-  &nsGkAtoms::aside,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::audio,
-#endif
-  &nsGkAtoms::b,
-  &nsGkAtoms::bdo,
-  &nsGkAtoms::big,
-  &nsGkAtoms::blockquote,
-  &nsGkAtoms::br,
-  &nsGkAtoms::button,
-  &nsGkAtoms::canvas,
-  &nsGkAtoms::caption,
-  &nsGkAtoms::center,
-  &nsGkAtoms::cite,
-  &nsGkAtoms::code,
-  &nsGkAtoms::col,
-  &nsGkAtoms::colgroup,
-  &nsGkAtoms::command,
-  &nsGkAtoms::datalist,
-  &nsGkAtoms::dd,
-  &nsGkAtoms::del,
-  &nsGkAtoms::details,
-  &nsGkAtoms::dfn,
-  &nsGkAtoms::dir,
-  &nsGkAtoms::div,
-  &nsGkAtoms::dl,
-  &nsGkAtoms::dt,
-  &nsGkAtoms::em,
-  &nsGkAtoms::fieldset,
-  &nsGkAtoms::figcaption,
-  &nsGkAtoms::figure,
-  &nsGkAtoms::font,
-  &nsGkAtoms::footer,
-  &nsGkAtoms::form,
-  &nsGkAtoms::h1,
-  &nsGkAtoms::h2,
-  &nsGkAtoms::h3,
-  &nsGkAtoms::h4,
-  &nsGkAtoms::h5,
-  &nsGkAtoms::h6,
-  &nsGkAtoms::header,
-  &nsGkAtoms::hgroup,
-  &nsGkAtoms::hr,
-  &nsGkAtoms::i,
-  &nsGkAtoms::img,
-  &nsGkAtoms::input,
-  &nsGkAtoms::ins,
-  &nsGkAtoms::kbd,
-  &nsGkAtoms::label,
-  &nsGkAtoms::legend,
-  &nsGkAtoms::li,
-  &nsGkAtoms::listing,
-  &nsGkAtoms::map,
-  &nsGkAtoms::mark,
-  &nsGkAtoms::menu,
-  &nsGkAtoms::meter,
-  &nsGkAtoms::nav,
-  &nsGkAtoms::nobr,
-  &nsGkAtoms::noscript,
-  &nsGkAtoms::ol,
-  &nsGkAtoms::optgroup,
-  &nsGkAtoms::option,
-  &nsGkAtoms::output,
-  &nsGkAtoms::p,
-  &nsGkAtoms::pre,
-  &nsGkAtoms::progress,
-  &nsGkAtoms::q,
-  &nsGkAtoms::rp,
-  &nsGkAtoms::rt,
-  &nsGkAtoms::ruby,
-  &nsGkAtoms::s,
-  &nsGkAtoms::samp,
-  &nsGkAtoms::section,
-  &nsGkAtoms::select,
-  &nsGkAtoms::small,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::source,
-#endif
-  &nsGkAtoms::span,
-  &nsGkAtoms::strike,
-  &nsGkAtoms::strong,
-  &nsGkAtoms::sub,
-  &nsGkAtoms::summary,
-  &nsGkAtoms::sup,
-  &nsGkAtoms::table,
-  &nsGkAtoms::tbody,
-  &nsGkAtoms::td,
-  &nsGkAtoms::textarea,
-  &nsGkAtoms::tfoot,
-  &nsGkAtoms::th,
-  &nsGkAtoms::thead,
-  &nsGkAtoms::time,
-  &nsGkAtoms::tr,
-  &nsGkAtoms::track,
-  &nsGkAtoms::tt,
-  &nsGkAtoms::u,
-  &nsGkAtoms::ul,
-  &nsGkAtoms::var,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::video,
-#endif
-  &nsGkAtoms::wbr,
-  nsnull
-};
-
-nsIAtom** const kDefaultAllowedAttributes [] = {
-  &nsGkAtoms::abbr,
-  &nsGkAtoms::accept,
-  &nsGkAtoms::acceptcharset,
-  &nsGkAtoms::accesskey,
-  &nsGkAtoms::action,
-  &nsGkAtoms::align,
-  &nsGkAtoms::alt,
-  &nsGkAtoms::autocomplete,
-  &nsGkAtoms::autofocus,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::autoplay,
-#endif
-  &nsGkAtoms::axis,
-  &nsGkAtoms::background,
-  &nsGkAtoms::bgcolor,
-  &nsGkAtoms::border,
-  &nsGkAtoms::cellpadding,
-  &nsGkAtoms::cellspacing,
-  &nsGkAtoms::_char,
-  &nsGkAtoms::charoff,
-  &nsGkAtoms::charset,
-  &nsGkAtoms::checked,
-  &nsGkAtoms::cite,
-  &nsGkAtoms::_class,
-  &nsGkAtoms::clear,
-  &nsGkAtoms::cols,
-  &nsGkAtoms::colspan,
-  &nsGkAtoms::color,
-  &nsGkAtoms::contenteditable,
-  &nsGkAtoms::contextmenu,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::controls,
-#endif
-  &nsGkAtoms::compact,
-  &nsGkAtoms::coords,
-  &nsGkAtoms::datetime,
-  &nsGkAtoms::dir,
-  &nsGkAtoms::disabled,
-  &nsGkAtoms::draggable,
-  &nsGkAtoms::enctype,
-  &nsGkAtoms::face,
-  &nsGkAtoms::_for,
-  &nsGkAtoms::frame,
-  &nsGkAtoms::headers,
-  &nsGkAtoms::height,
-  &nsGkAtoms::hidden,
-  &nsGkAtoms::high,
-  &nsGkAtoms::href,
-  &nsGkAtoms::hreflang,
-  &nsGkAtoms::hspace,
-  &nsGkAtoms::icon,
-  &nsGkAtoms::id,
-  &nsGkAtoms::ismap,
-  &nsGkAtoms::itemid,
-  &nsGkAtoms::itemprop,
-  &nsGkAtoms::itemref,
-  &nsGkAtoms::itemscope,
-  &nsGkAtoms::itemtype,
-  &nsGkAtoms::kind,
-  &nsGkAtoms::label,
-  &nsGkAtoms::lang,
-  &nsGkAtoms::list,
-  &nsGkAtoms::longdesc,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::loop,
-  &nsGkAtoms::loopend,
-  &nsGkAtoms::loopstart,
-#endif
-  &nsGkAtoms::low,
-  &nsGkAtoms::max,
-  &nsGkAtoms::maxlength,
-  &nsGkAtoms::media,
-  &nsGkAtoms::method,
-  &nsGkAtoms::min,
-  &nsGkAtoms::mozdonotsend,
-  &nsGkAtoms::multiple,
-  &nsGkAtoms::name,
-  &nsGkAtoms::nohref,
-  &nsGkAtoms::noshade,
-  &nsGkAtoms::novalidate,
-  &nsGkAtoms::nowrap,
-  &nsGkAtoms::open,
-  &nsGkAtoms::optimum,
-  &nsGkAtoms::pattern,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::pixelratio,
-#endif
-  &nsGkAtoms::placeholder,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::playbackrate,
-  &nsGkAtoms::playcount,
-#endif
-  &nsGkAtoms::pointSize,
-#ifdef MOZ_MEDIA
-  &nsGkAtoms::poster,
-  &nsGkAtoms::preload,
-#endif
-  &nsGkAtoms::prompt,
-  &nsGkAtoms::pubdate,
-  &nsGkAtoms::radiogroup,
-  &nsGkAtoms::readonly,
-  &nsGkAtoms::rel,
-  &nsGkAtoms::required,
-  &nsGkAtoms::rev,
-  &nsGkAtoms::reversed,
-  &nsGkAtoms::role,
-  &nsGkAtoms::rows,
-  &nsGkAtoms::rowspan,
-  &nsGkAtoms::rules,
-  &nsGkAtoms::scoped,
-  &nsGkAtoms::scope,
-  &nsGkAtoms::selected,
-  &nsGkAtoms::shape,
-  &nsGkAtoms::size,
-  &nsGkAtoms::span,
-  &nsGkAtoms::spellcheck,
-  &nsGkAtoms::src,
-  &nsGkAtoms::srclang,
-  &nsGkAtoms::start,
-  &nsGkAtoms::summary,
-  &nsGkAtoms::tabindex,
-  &nsGkAtoms::target,
-  &nsGkAtoms::title,
-  &nsGkAtoms::type,
-  &nsGkAtoms::usemap,
-  &nsGkAtoms::valign,
-  &nsGkAtoms::value,
-  &nsGkAtoms::vspace,
-  &nsGkAtoms::width,
-  &nsGkAtoms::wrap,
-  nsnull
-};
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -402,14 +402,9 @@ protected:
   static PRInt32 sInteractiveTime;
   // How long to stay in perf mode after initial loading
   static PRInt32 sInitialPerfTime;
   // Should we switch between perf-mode and interactive-mode
   static PRInt32 sEnablePerfMode;
   static PRBool sCanInterruptParser;
 };
 
-// sanitizing content sink whitelists
-extern PRBool IsAttrURI(nsIAtom *aName);
-extern nsIAtom** const kDefaultAllowedTags [];
-extern nsIAtom** const kDefaultAllowedAttributes [];
-
 #endif // _nsContentSink_h_
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1082,19 +1082,16 @@ nsContentUtils::OfflineAppAllowed(nsIPri
 }
 
 // static
 void
 nsContentUtils::Shutdown()
 {
   sInitialized = PR_FALSE;
 
-  NS_HTMLParanoidFragmentSinkShutdown();
-  NS_XHTMLParanoidFragmentSinkShutdown();
-
   NS_IF_RELEASE(sContentPolicyService);
   sTriedToGetContentPolicy = PR_FALSE;
   PRUint32 i;
   for (i = 0; i < PropertiesFile_COUNT; ++i)
     NS_IF_RELEASE(sStringBundles[i]);
 
   NS_IF_RELEASE(sStringBundleService);
   NS_IF_RELEASE(sConsoleService);
new file mode 100644
--- /dev/null
+++ b/content/base/src/nsTreeSanitizer.cpp
@@ -0,0 +1,1498 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=2 et tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Robert Sayre <sayrer@gmail.com>
+ *   Henri Sivonen <hsivonen@iki.fi>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsTreeSanitizer.h"
+#include "nsCSSParser.h"
+#include "nsCSSProperty.h"
+#include "mozilla/css/Declaration.h"
+#include "mozilla/css/StyleRule.h"
+#include "mozilla/css/Rule.h"
+#include "nsUnicharInputStream.h"
+#include "nsCSSStyleSheet.h"
+#include "nsIDOMCSSRule.h"
+#include "nsAttrName.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsNetUtil.h"
+#include "nsComponentManagerUtils.h"
+#include "nsNullPrincipal.h"
+
+//
+// Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
+//
+nsIAtom** const kElementsHTML[] = {
+  &nsGkAtoms::a,
+  &nsGkAtoms::abbr,
+  &nsGkAtoms::acronym,
+  &nsGkAtoms::address,
+  &nsGkAtoms::area,
+  &nsGkAtoms::article,
+  &nsGkAtoms::aside,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::audio,
+#endif
+  &nsGkAtoms::b,
+  &nsGkAtoms::bdo,
+  &nsGkAtoms::big,
+  &nsGkAtoms::blockquote,
+  &nsGkAtoms::br,
+  &nsGkAtoms::button,
+  &nsGkAtoms::canvas,
+  &nsGkAtoms::caption,
+  &nsGkAtoms::center,
+  &nsGkAtoms::cite,
+  &nsGkAtoms::code,
+  &nsGkAtoms::col,
+  &nsGkAtoms::colgroup,
+  &nsGkAtoms::command,
+  &nsGkAtoms::datalist,
+  &nsGkAtoms::dd,
+  &nsGkAtoms::del,
+  &nsGkAtoms::details,
+  &nsGkAtoms::dfn,
+  &nsGkAtoms::dir,
+  &nsGkAtoms::div,
+  &nsGkAtoms::dl,
+  &nsGkAtoms::dt,
+  &nsGkAtoms::em,
+  &nsGkAtoms::fieldset,
+  &nsGkAtoms::figcaption,
+  &nsGkAtoms::figure,
+  &nsGkAtoms::font,
+  &nsGkAtoms::footer,
+  &nsGkAtoms::form,
+  &nsGkAtoms::h1,
+  &nsGkAtoms::h2,
+  &nsGkAtoms::h3,
+  &nsGkAtoms::h4,
+  &nsGkAtoms::h5,
+  &nsGkAtoms::h6,
+  &nsGkAtoms::header,
+  &nsGkAtoms::hgroup,
+  &nsGkAtoms::hr,
+  &nsGkAtoms::i,
+  &nsGkAtoms::img,
+  &nsGkAtoms::input,
+  &nsGkAtoms::ins,
+  &nsGkAtoms::kbd,
+  &nsGkAtoms::label,
+  &nsGkAtoms::legend,
+  &nsGkAtoms::li,
+  &nsGkAtoms::link,
+  &nsGkAtoms::listing,
+  &nsGkAtoms::map,
+  &nsGkAtoms::mark,
+  &nsGkAtoms::menu,
+  &nsGkAtoms::meta,
+  &nsGkAtoms::meter,
+  &nsGkAtoms::nav,
+  &nsGkAtoms::nobr,
+  &nsGkAtoms::noscript,
+  &nsGkAtoms::ol,
+  &nsGkAtoms::optgroup,
+  &nsGkAtoms::option,
+  &nsGkAtoms::output,
+  &nsGkAtoms::p,
+  &nsGkAtoms::pre,
+  &nsGkAtoms::progress,
+  &nsGkAtoms::q,
+  &nsGkAtoms::rp,
+  &nsGkAtoms::rt,
+  &nsGkAtoms::ruby,
+  &nsGkAtoms::s,
+  &nsGkAtoms::samp,
+  &nsGkAtoms::section,
+  &nsGkAtoms::select,
+  &nsGkAtoms::small,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::source,
+#endif
+  &nsGkAtoms::span,
+  &nsGkAtoms::strike,
+  &nsGkAtoms::strong,
+  &nsGkAtoms::sub,
+  &nsGkAtoms::summary,
+  &nsGkAtoms::sup,
+  &nsGkAtoms::table,
+  &nsGkAtoms::tbody,
+  &nsGkAtoms::td,
+  &nsGkAtoms::textarea,
+  &nsGkAtoms::tfoot,
+  &nsGkAtoms::th,
+  &nsGkAtoms::thead,
+  &nsGkAtoms::time,
+  &nsGkAtoms::tr,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::track,
+#endif
+  &nsGkAtoms::tt,
+  &nsGkAtoms::u,
+  &nsGkAtoms::ul,
+  &nsGkAtoms::var,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::video,
+#endif
+  &nsGkAtoms::wbr,
+  nsnull
+};
+
+nsIAtom** const kAttributesHTML[] = {
+  &nsGkAtoms::abbr,
+  &nsGkAtoms::accept,
+  &nsGkAtoms::acceptcharset,
+  &nsGkAtoms::accesskey,
+  &nsGkAtoms::action,
+  &nsGkAtoms::align,
+  &nsGkAtoms::alt,
+  &nsGkAtoms::autocomplete,
+  &nsGkAtoms::autofocus,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::autoplay,
+#endif
+  &nsGkAtoms::axis,
+  &nsGkAtoms::background,
+  &nsGkAtoms::bgcolor,
+  &nsGkAtoms::border,
+  &nsGkAtoms::cellpadding,
+  &nsGkAtoms::cellspacing,
+  &nsGkAtoms::_char,
+  &nsGkAtoms::charoff,
+  &nsGkAtoms::charset,
+  &nsGkAtoms::checked,
+  &nsGkAtoms::cite,
+  &nsGkAtoms::_class,
+  &nsGkAtoms::clear,
+  &nsGkAtoms::cols,
+  &nsGkAtoms::colspan,
+  &nsGkAtoms::color,
+  &nsGkAtoms::contenteditable,
+  &nsGkAtoms::contextmenu,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::controls,
+#endif
+  &nsGkAtoms::compact,
+  &nsGkAtoms::coords,
+  &nsGkAtoms::datetime,
+  &nsGkAtoms::dir,
+  &nsGkAtoms::disabled,
+  &nsGkAtoms::draggable,
+  &nsGkAtoms::enctype,
+  &nsGkAtoms::face,
+  &nsGkAtoms::_for,
+  &nsGkAtoms::frame,
+  &nsGkAtoms::headers,
+  &nsGkAtoms::height,
+  &nsGkAtoms::hidden,
+  &nsGkAtoms::high,
+  &nsGkAtoms::href,
+  &nsGkAtoms::hreflang,
+  &nsGkAtoms::hspace,
+  &nsGkAtoms::icon,
+  &nsGkAtoms::id,
+  &nsGkAtoms::ismap,
+  &nsGkAtoms::itemid,
+  &nsGkAtoms::itemprop,
+  &nsGkAtoms::itemref,
+  &nsGkAtoms::itemscope,
+  &nsGkAtoms::itemtype,
+  &nsGkAtoms::kind,
+  &nsGkAtoms::label,
+  &nsGkAtoms::lang,
+  &nsGkAtoms::list,
+  &nsGkAtoms::longdesc,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::loop,
+  &nsGkAtoms::loopend,
+  &nsGkAtoms::loopstart,
+#endif
+  &nsGkAtoms::low,
+  &nsGkAtoms::max,
+  &nsGkAtoms::maxlength,
+  &nsGkAtoms::media,
+  &nsGkAtoms::method,
+  &nsGkAtoms::min,
+  &nsGkAtoms::mozdonotsend,
+  &nsGkAtoms::multiple,
+  &nsGkAtoms::name,
+  &nsGkAtoms::nohref,
+  &nsGkAtoms::noshade,
+  &nsGkAtoms::novalidate,
+  &nsGkAtoms::nowrap,
+  &nsGkAtoms::open,
+  &nsGkAtoms::optimum,
+  &nsGkAtoms::pattern,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::pixelratio,
+#endif
+  &nsGkAtoms::placeholder,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::playbackrate,
+  &nsGkAtoms::playcount,
+#endif
+  &nsGkAtoms::pointSize,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::poster,
+  &nsGkAtoms::preload,
+#endif
+  &nsGkAtoms::prompt,
+  &nsGkAtoms::pubdate,
+  &nsGkAtoms::radiogroup,
+  &nsGkAtoms::readonly,
+  &nsGkAtoms::rel,
+  &nsGkAtoms::required,
+  &nsGkAtoms::rev,
+  &nsGkAtoms::reversed,
+  &nsGkAtoms::role,
+  &nsGkAtoms::rows,
+  &nsGkAtoms::rowspan,
+  &nsGkAtoms::rules,
+  &nsGkAtoms::scoped,
+  &nsGkAtoms::scope,
+  &nsGkAtoms::selected,
+  &nsGkAtoms::shape,
+  &nsGkAtoms::size,
+  &nsGkAtoms::span,
+  &nsGkAtoms::spellcheck,
+  &nsGkAtoms::src,
+  &nsGkAtoms::srclang,
+  &nsGkAtoms::start,
+  &nsGkAtoms::summary,
+  &nsGkAtoms::tabindex,
+  &nsGkAtoms::target,
+  &nsGkAtoms::title,
+  &nsGkAtoms::type,
+  &nsGkAtoms::usemap,
+  &nsGkAtoms::valign,
+  &nsGkAtoms::value,
+  &nsGkAtoms::vspace,
+  &nsGkAtoms::width,
+  &nsGkAtoms::wrap,
+  nsnull
+};
+
+nsIAtom** const kURLAttributesHTML[] = {
+  &nsGkAtoms::action,
+  &nsGkAtoms::href,
+  &nsGkAtoms::src,
+  &nsGkAtoms::longdesc,
+  &nsGkAtoms::cite,
+  &nsGkAtoms::background,
+  nsnull
+};
+
+nsIAtom** const kElementsSVG[] = {
+#ifdef MOZ_SVG
+  &nsGkAtoms::a, // a
+  &nsGkAtoms::altGlyph, // altGlyph
+  &nsGkAtoms::altGlyphDef, // altGlyphDef
+  &nsGkAtoms::altGlyphItem, // altGlyphItem
+  &nsGkAtoms::animate, // animate
+  &nsGkAtoms::animateColor, // animateColor
+  &nsGkAtoms::animateMotion, // animateMotion
+  &nsGkAtoms::animateTransform, // animateTransform
+  &nsGkAtoms::circle, // circle
+  &nsGkAtoms::clipPath, // clipPath
+  &nsGkAtoms::colorProfile, // color-profile
+  &nsGkAtoms::cursor, // cursor
+  &nsGkAtoms::defs, // defs
+  &nsGkAtoms::desc, // desc
+  &nsGkAtoms::ellipse, // ellipse
+  &nsGkAtoms::elevation, // elevation
+  &nsGkAtoms::erode, // erode
+  &nsGkAtoms::ex, // ex
+  &nsGkAtoms::exact, // exact
+  &nsGkAtoms::exponent, // exponent
+  &nsGkAtoms::feBlend, // feBlend
+  &nsGkAtoms::feColorMatrix, // feColorMatrix
+  &nsGkAtoms::feComponentTransfer, // feComponentTransfer
+  &nsGkAtoms::feComposite, // feComposite
+  &nsGkAtoms::feConvolveMatrix, // feConvolveMatrix
+  &nsGkAtoms::feDiffuseLighting, // feDiffuseLighting
+  &nsGkAtoms::feDisplacementMap, // feDisplacementMap
+  &nsGkAtoms::feDistantLight, // feDistantLight
+  &nsGkAtoms::feFlood, // feFlood
+  &nsGkAtoms::feFuncA, // feFuncA
+  &nsGkAtoms::feFuncB, // feFuncB
+  &nsGkAtoms::feFuncG, // feFuncG
+  &nsGkAtoms::feFuncR, // feFuncR
+  &nsGkAtoms::feGaussianBlur, // feGaussianBlur
+  &nsGkAtoms::feImage, // feImage
+  &nsGkAtoms::feMerge, // feMerge
+  &nsGkAtoms::feMergeNode, // feMergeNode
+  &nsGkAtoms::feMorphology, // feMorphology
+  &nsGkAtoms::feOffset, // feOffset
+  &nsGkAtoms::fePointLight, // fePointLight
+  &nsGkAtoms::feSpecularLighting, // feSpecularLighting
+  &nsGkAtoms::feSpotLight, // feSpotLight
+  &nsGkAtoms::feTile, // feTile
+  &nsGkAtoms::feTurbulence, // feTurbulence
+  &nsGkAtoms::filter, // filter
+  &nsGkAtoms::font, // font
+  &nsGkAtoms::font_face, // font-face
+  &nsGkAtoms::font_face_format, // font-face-format
+  &nsGkAtoms::font_face_name, // font-face-name
+  &nsGkAtoms::font_face_src, // font-face-src
+  &nsGkAtoms::font_face_uri, // font-face-uri
+  &nsGkAtoms::foreignObject, // foreignObject
+  &nsGkAtoms::g, // g
+  &nsGkAtoms::glyph, // glyph
+  &nsGkAtoms::glyphRef, // glyphRef
+  &nsGkAtoms::hkern, // hkern
+  &nsGkAtoms::image, // image
+  &nsGkAtoms::line, // line
+  &nsGkAtoms::linearGradient, // linearGradient
+  &nsGkAtoms::marker, // marker
+  &nsGkAtoms::mask, // mask
+  &nsGkAtoms::metadata, // metadata
+  &nsGkAtoms::missingGlyph, // missingGlyph
+  &nsGkAtoms::mpath, // mpath
+  &nsGkAtoms::path, // path
+  &nsGkAtoms::pattern, // pattern
+  &nsGkAtoms::polygon, // polygon
+  &nsGkAtoms::polyline, // polyline
+  &nsGkAtoms::radialGradient, // radialGradient
+  &nsGkAtoms::rect, // rect
+  &nsGkAtoms::set, // set
+  &nsGkAtoms::stop, // stop
+  &nsGkAtoms::svg, // svg
+  &nsGkAtoms::svgSwitch, // switch
+  &nsGkAtoms::symbol, // symbol
+  &nsGkAtoms::text, // text
+  &nsGkAtoms::textPath, // textPath
+  &nsGkAtoms::title, // title
+  &nsGkAtoms::tref, // tref
+  &nsGkAtoms::tspan, // tspan
+  &nsGkAtoms::use, // use
+  &nsGkAtoms::view, // view
+  &nsGkAtoms::vkern, // vkern
+#endif
+  nsnull
+};
+
+nsIAtom** const kAttributesSVG[] = {
+#ifdef MOZ_SVG
+  // accent-height
+#ifdef MOZ_SMIL
+  &nsGkAtoms::accumulate, // accumulate
+  &nsGkAtoms::additive, // additive
+#endif
+  &nsGkAtoms::alignment_baseline, // alignment-baseline
+  // alphabetic
+  &nsGkAtoms::amplitude, // amplitude
+  // arabic-form
+  // ascent
+#ifdef MOZ_SMIL
+  &nsGkAtoms::attributeName, // attributeName
+  &nsGkAtoms::attributeType, // attributeType
+#endif
+  &nsGkAtoms::azimuth, // azimuth
+  &nsGkAtoms::baseFrequency, // baseFrequency
+  &nsGkAtoms::baseline_shift, // baseline-shift
+  // baseProfile
+  // bbox
+#ifdef MOZ_SMIL
+  &nsGkAtoms::begin, // begin
+#endif
+  &nsGkAtoms::bias, // bias
+#ifdef MOZ_SMIL
+  &nsGkAtoms::by, // by
+  &nsGkAtoms::calcMode, // calcMode
+#endif
+  // cap-height
+  &nsGkAtoms::_class, // class
+  &nsGkAtoms::clip_path, // clip-path
+  &nsGkAtoms::clip_rule, // clip-rule
+  &nsGkAtoms::clipPathUnits, // clipPathUnits
+  &nsGkAtoms::color, // color
+  &nsGkAtoms::colorInterpolation, // color-interpolation
+  &nsGkAtoms::colorInterpolationFilters, // color-interpolation-filters
+  // contentScriptType
+  // contentStyleType
+  &nsGkAtoms::cursor, // cursor
+  &nsGkAtoms::cx, // cx
+  &nsGkAtoms::cy, // cy
+  &nsGkAtoms::d, // d
+  // descent
+  &nsGkAtoms::diffuseConstant, // diffuseConstant
+  &nsGkAtoms::direction, // direction
+  &nsGkAtoms::display, // display
+  &nsGkAtoms::divisor, // divisor
+  &nsGkAtoms::dominant_baseline, // dominant-baseline
+#ifdef MOZ_SMIL
+  &nsGkAtoms::dur, // dur
+#endif
+  &nsGkAtoms::dx, // dx
+  &nsGkAtoms::dy, // dy
+  &nsGkAtoms::edgeMode, // edgeMode
+  &nsGkAtoms::elevation, // elevation
+  // enable-background
+#ifdef MOZ_SMIL
+  &nsGkAtoms::end, // end
+#endif
+  &nsGkAtoms::fill, // fill
+  &nsGkAtoms::fill_opacity, // fill-opacity
+  &nsGkAtoms::fill_rule, // fill-rule
+  &nsGkAtoms::filter, // filter
+  &nsGkAtoms::filterRes, // filterRes
+  &nsGkAtoms::filterUnits, // filterUnits
+  &nsGkAtoms::flood_color, // flood-color
+  &nsGkAtoms::flood_opacity, // flood-opacity
+  // XXX focusable
+  &nsGkAtoms::font, // font
+  &nsGkAtoms::font_family, // font-family
+  &nsGkAtoms::font_size, // font-size
+  &nsGkAtoms::font_size_adjust, // font-size-adjust
+  &nsGkAtoms::font_stretch, // font-stretch
+  &nsGkAtoms::font_style, // font-style
+  &nsGkAtoms::font_variant, // font-variant
+  &nsGkAtoms::fontWeight, // font-weight
+  &nsGkAtoms::format, // format
+  &nsGkAtoms::from, // from
+  &nsGkAtoms::fx, // fx
+  &nsGkAtoms::fy, // fy
+  // g1
+  // g2
+  // glyph-name
+  // glyphRef
+  &nsGkAtoms::glyph_orientation_horizontal, // glyph-orientation-horizontal
+  &nsGkAtoms::glyph_orientation_vertical, // glyph-orientation-vertical
+  &nsGkAtoms::gradientTransform, // gradientTransform
+  &nsGkAtoms::gradientUnits, // gradientUnits
+  &nsGkAtoms::height, // height
+  // horiz-adv-x
+  // horiz-origin-x
+  // horiz-origin-y
+  &nsGkAtoms::id, // id
+  // ideographic
+  &nsGkAtoms::image_rendering, // image-rendering
+  &nsGkAtoms::in, // in
+  &nsGkAtoms::in2, // in2
+  &nsGkAtoms::intercept, // intercept
+  // k
+  &nsGkAtoms::k1, // k1
+  &nsGkAtoms::k2, // k2
+  &nsGkAtoms::k3, // k3
+  &nsGkAtoms::k4, // k4
+  &nsGkAtoms::kerning, // kerning
+  &nsGkAtoms::kernelMatrix, // kernelMatrix
+  &nsGkAtoms::kernelUnitLength, // kernelUnitLength
+#ifdef MOZ_SMIL
+  &nsGkAtoms::keyPoints, // keyPoints
+  &nsGkAtoms::keySplines, // keySplines
+  &nsGkAtoms::keyTimes, // keyTimes
+#endif
+  &nsGkAtoms::lang, // lang
+  // lengthAdjust
+  &nsGkAtoms::letter_spacing, // letter-spacing
+  &nsGkAtoms::lighting_color, // lighting-color
+  &nsGkAtoms::limitingConeAngle, // limitingConeAngle
+  // local
+  &nsGkAtoms::marker, // marker
+  &nsGkAtoms::marker_end, // marker-end
+  &nsGkAtoms::marker_mid, // marker-mid
+  &nsGkAtoms::marker_start, // marker-start
+  &nsGkAtoms::markerHeight, // markerHeight
+  &nsGkAtoms::markerUnits, // markerUnits
+  &nsGkAtoms::markerWidth, // markerWidth
+  &nsGkAtoms::mask, // mask
+  &nsGkAtoms::maskContentUnits, // maskContentUnits
+  &nsGkAtoms::maskUnits, // maskUnits
+  // mathematical
+  &nsGkAtoms::max, // max
+  &nsGkAtoms::media, // media
+  &nsGkAtoms::method, // method
+  &nsGkAtoms::min, // min
+  &nsGkAtoms::mode, // mode
+  &nsGkAtoms::name, // name
+  &nsGkAtoms::numOctaves, // numOctaves
+  &nsGkAtoms::offset, // offset
+  &nsGkAtoms::opacity, // opacity
+  &nsGkAtoms::_operator, // operator
+  &nsGkAtoms::order, // order
+  &nsGkAtoms::orient, // orient
+  &nsGkAtoms::orientation, // orientation
+  // origin
+  // overline-position
+  // overline-thickness
+  &nsGkAtoms::overflow, // overflow
+  // panose-1
+  &nsGkAtoms::path, // path
+  &nsGkAtoms::pathLength, // pathLength
+  &nsGkAtoms::patternContentUnits, // patternContentUnits
+  &nsGkAtoms::patternTransform, // patternTransform
+  &nsGkAtoms::patternUnits, // patternUnits
+  &nsGkAtoms::pointer_events, // pointer-events XXX is this safe?
+  &nsGkAtoms::points, // points
+  &nsGkAtoms::pointsAtX, // pointsAtX
+  &nsGkAtoms::pointsAtY, // pointsAtY
+  &nsGkAtoms::pointsAtZ, // pointsAtZ
+  &nsGkAtoms::preserveAlpha, // preserveAlpha
+  &nsGkAtoms::preserveAspectRatio, // preserveAspectRatio
+  &nsGkAtoms::primitiveUnits, // primitiveUnits
+  &nsGkAtoms::r, // r
+  &nsGkAtoms::radius, // radius
+  &nsGkAtoms::refX, // refX
+  &nsGkAtoms::refY, // refY
+#ifdef MOZ_SMIL
+  &nsGkAtoms::repeatCount, // repeatCount
+  &nsGkAtoms::repeatDur, // repeatDur
+#endif
+  &nsGkAtoms::requiredExtensions, // requiredExtensions
+  &nsGkAtoms::requiredFeatures, // requiredFeatures
+#ifdef MOZ_SMIL
+  &nsGkAtoms::restart, // restart
+#endif
+  &nsGkAtoms::result, // result
+  &nsGkAtoms::rotate, // rotate
+  &nsGkAtoms::rx, // rx
+  &nsGkAtoms::ry, // ry
+  &nsGkAtoms::scale, // scale
+  &nsGkAtoms::seed, // seed
+  &nsGkAtoms::shape_rendering, // shape-rendering
+  &nsGkAtoms::slope, // slope
+  &nsGkAtoms::spacing, // spacing
+  &nsGkAtoms::specularConstant, // specularConstant
+  &nsGkAtoms::specularExponent, // specularExponent
+  &nsGkAtoms::spreadMethod, // spreadMethod
+  &nsGkAtoms::startOffset, // startOffset
+  &nsGkAtoms::stdDeviation, // stdDeviation
+  // stemh
+  // stemv
+  &nsGkAtoms::stitchTiles, // stitchTiles
+  &nsGkAtoms::stop_color, // stop-color
+  &nsGkAtoms::stop_opacity, // stop-opacity
+  // strikethrough-position
+  // strikethrough-thickness
+  &nsGkAtoms::string, // string
+  &nsGkAtoms::stroke, // stroke
+  &nsGkAtoms::stroke_dasharray, // stroke-dasharray
+  &nsGkAtoms::stroke_dashoffset, // stroke-dashoffset
+  &nsGkAtoms::stroke_linecap, // stroke-linecap
+  &nsGkAtoms::stroke_linejoin, // stroke-linejoin
+  &nsGkAtoms::stroke_miterlimit, // stroke-miterlimit
+  &nsGkAtoms::stroke_opacity, // stroke-opacity
+  &nsGkAtoms::stroke_width, // stroke-width
+  &nsGkAtoms::surfaceScale, // surfaceScale
+  &nsGkAtoms::systemLanguage, // systemLanguage
+  &nsGkAtoms::tableValues, // tableValues
+  &nsGkAtoms::target, // target
+  &nsGkAtoms::targetX, // targetX
+  &nsGkAtoms::targetY, // targetY
+  &nsGkAtoms::text_anchor, // text-anchor
+  &nsGkAtoms::text_decoration, // text-decoration
+  // textLength
+  &nsGkAtoms::text_rendering, // text-rendering
+  &nsGkAtoms::title, // title
+#ifdef MOZ_SMIL
+  &nsGkAtoms::to, // to
+#endif
+  &nsGkAtoms::transform, // transform
+  &nsGkAtoms::type, // type
+  // u1
+  // u2
+  // underline-position
+  // underline-thickness
+  // unicode
+  &nsGkAtoms::unicode_bidi, // unicode-bidi
+  // unicode-range
+  // units-per-em
+  // v-alphabetic
+  // v-hanging
+  // v-ideographic
+  // v-mathematical
+  &nsGkAtoms::values, // values
+  // vert-adv-y
+  // vert-origin-x
+  // vert-origin-y
+  &nsGkAtoms::viewBox, // viewBox
+  &nsGkAtoms::visibility, // visibility
+  // viewTarget
+  &nsGkAtoms::width, // width
+  // widths
+  &nsGkAtoms::word_spacing, // word-spacing
+  // writing-mode
+  &nsGkAtoms::x, // x
+  // x-height
+  &nsGkAtoms::x1, // x1
+  &nsGkAtoms::x2, // x2
+  &nsGkAtoms::xChannelSelector, // xChannelSelector
+  &nsGkAtoms::y, // y
+  &nsGkAtoms::y1, // y1
+  &nsGkAtoms::y2, // y2
+  &nsGkAtoms::yChannelSelector, // yChannelSelector
+  &nsGkAtoms::z, // z
+  &nsGkAtoms::zoomAndPan, // zoomAndPan
+#endif
+  nsnull
+};
+
+nsIAtom** const kURLAttributesSVG[] = {
+  nsnull
+};
+
+nsIAtom** const kElementsMathML[] = {
+   &nsGkAtoms::abs_, // abs
+   &nsGkAtoms::_and, // and
+   &nsGkAtoms::annotation_, // annotation
+   &nsGkAtoms::annotation_xml_, // annotation-xml
+   &nsGkAtoms::apply_, // apply
+   &nsGkAtoms::approx_, // approx
+   &nsGkAtoms::arccos_, // arccos
+   &nsGkAtoms::arccosh_, // arccosh
+   &nsGkAtoms::arccot_, // arccot
+   &nsGkAtoms::arccoth_, // arccoth
+   &nsGkAtoms::arccsc_, // arccsc
+   &nsGkAtoms::arccsch_, // arccsch
+   &nsGkAtoms::arcsec_, // arcsec
+   &nsGkAtoms::arcsech_, // arcsech
+   &nsGkAtoms::arcsin_, // arcsin
+   &nsGkAtoms::arcsinh_, // arcsinh
+   &nsGkAtoms::arctan_, // arctan
+   &nsGkAtoms::arctanh_, // arctanh
+   &nsGkAtoms::arg_, // arg
+   &nsGkAtoms::bind_, // bind
+   &nsGkAtoms::bvar_, // bvar
+   &nsGkAtoms::card_, // card
+   &nsGkAtoms::cartesianproduct_, // cartesianproduct
+   &nsGkAtoms::cbytes_, // cbytes
+   &nsGkAtoms::ceiling, // ceiling
+   &nsGkAtoms::cerror_, // cerror
+   &nsGkAtoms::ci_, // ci
+   &nsGkAtoms::cn_, // cn
+   &nsGkAtoms::codomain_, // codomain
+   &nsGkAtoms::complexes_, // complexes
+   &nsGkAtoms::compose_, // compose
+   &nsGkAtoms::condition_, // condition
+   &nsGkAtoms::conjugate_, // conjugate
+   &nsGkAtoms::cos_, // cos
+   &nsGkAtoms::cosh_, // cosh
+   &nsGkAtoms::cot_, // cot
+   &nsGkAtoms::coth_, // coth
+   &nsGkAtoms::cs_, // cs
+   &nsGkAtoms::csc_, // csc
+   &nsGkAtoms::csch_, // csch
+   &nsGkAtoms::csymbol_, // csymbol
+   &nsGkAtoms::curl_, // curl
+   &nsGkAtoms::declare, // declare
+   &nsGkAtoms::degree_, // degree
+   &nsGkAtoms::determinant_, // determinant
+   &nsGkAtoms::diff_, // diff
+   &nsGkAtoms::divergence_, // divergence
+   &nsGkAtoms::divide_, // divide
+   &nsGkAtoms::domain_, // domain
+   &nsGkAtoms::domainofapplication_, // domainofapplication
+   &nsGkAtoms::el_, // el
+   &nsGkAtoms::emptyset_, // emptyset
+   &nsGkAtoms::eq_, // eq
+   &nsGkAtoms::equivalent_, // equivalent
+   &nsGkAtoms::eulergamma_, // eulergamma
+   &nsGkAtoms::exists_, // exists
+   &nsGkAtoms::exp_, // exp
+   &nsGkAtoms::exponentiale_, // exponentiale
+   &nsGkAtoms::factorial_, // factorial
+   &nsGkAtoms::factorof_, // factorof
+   &nsGkAtoms::_false, // false
+   &nsGkAtoms::floor, // floor
+   &nsGkAtoms::fn_, // fn
+   &nsGkAtoms::forall_, // forall
+   &nsGkAtoms::gcd_, // gcd
+   &nsGkAtoms::geq_, // geq
+   &nsGkAtoms::grad, // grad
+   &nsGkAtoms::gt_, // gt
+   &nsGkAtoms::ident_, // ident
+   &nsGkAtoms::image, // image
+   &nsGkAtoms::imaginary_, // imaginary
+   &nsGkAtoms::imaginaryi_, // imaginaryi
+   &nsGkAtoms::implies_, // implies
+   &nsGkAtoms::in, // in
+   &nsGkAtoms::infinity, // infinity
+   &nsGkAtoms::int_, // int
+   &nsGkAtoms::integers_, // integers
+   &nsGkAtoms::intersect_, // intersect
+   &nsGkAtoms::interval_, // interval
+   &nsGkAtoms::inverse_, // inverse
+   &nsGkAtoms::lambda_, // lambda
+   &nsGkAtoms::laplacian_, // laplacian
+   &nsGkAtoms::lcm_, // lcm
+   &nsGkAtoms::leq_, // leq
+   &nsGkAtoms::limit_, // limit
+   &nsGkAtoms::list_, // list
+   &nsGkAtoms::ln_, // ln
+   &nsGkAtoms::log_, // log
+   &nsGkAtoms::logbase_, // logbase
+   &nsGkAtoms::lowlimit_, // lowlimit
+   &nsGkAtoms::lt_, // lt
+   &nsGkAtoms::maction_, // maction
+   &nsGkAtoms::malign_, // malign
+   &nsGkAtoms::maligngroup_, // maligngroup
+   &nsGkAtoms::malignmark_, // malignmark
+   &nsGkAtoms::malignscope_, // malignscope
+   &nsGkAtoms::math, // math
+   &nsGkAtoms::matrix, // matrix
+   &nsGkAtoms::matrixrow_, // matrixrow
+   &nsGkAtoms::max, // max
+   &nsGkAtoms::mean_, // mean
+   &nsGkAtoms::median_, // median
+   &nsGkAtoms::menclose_, // menclose
+   &nsGkAtoms::merror_, // merror
+   &nsGkAtoms::mfenced_, // mfenced
+   &nsGkAtoms::mfrac_, // mfrac
+   &nsGkAtoms::mfraction_, // mfraction
+   &nsGkAtoms::mglyph_, // mglyph
+   &nsGkAtoms::mi_, // mi
+   &nsGkAtoms::min, // min
+   &nsGkAtoms::minus_, // minus
+   &nsGkAtoms::mlabeledtr_, // mlabeledtr
+   &nsGkAtoms::mlongdiv_, // mlongdiv
+   &nsGkAtoms::mmultiscripts_, // mmultiscripts
+   &nsGkAtoms::mn_, // mn
+   &nsGkAtoms::mo_, // mo
+   &nsGkAtoms::mode, // mode
+   &nsGkAtoms::moment_, // moment
+   &nsGkAtoms::momentabout_, // momentabout
+   &nsGkAtoms::mover_, // mover
+   &nsGkAtoms::mpadded_, // mpadded
+   &nsGkAtoms::mphantom_, // mphantom
+   &nsGkAtoms::mprescripts_, // mprescripts
+   &nsGkAtoms::mroot_, // mroot
+   &nsGkAtoms::mrow_, // mrow
+   &nsGkAtoms::ms_, // ms
+   &nsGkAtoms::mscarries_, // mscarries
+   &nsGkAtoms::mscarry_, // mscarry
+   &nsGkAtoms::msgroup_, // msgroup
+   &nsGkAtoms::msline_, // msline
+   &nsGkAtoms::mspace_, // mspace
+   &nsGkAtoms::msqrt_, // msqrt
+   &nsGkAtoms::msrow_, // msrow
+   &nsGkAtoms::mstack_, // mstack
+   &nsGkAtoms::mstyle_, // mstyle
+   &nsGkAtoms::msub_, // msub
+   &nsGkAtoms::msubsup_, // msubsup
+   &nsGkAtoms::msup_, // msup
+   &nsGkAtoms::mtable_, // mtable
+   &nsGkAtoms::mtd_, // mtd
+   &nsGkAtoms::mtext_, // mtext
+   &nsGkAtoms::mtr_, // mtr
+   &nsGkAtoms::munder_, // munder
+   &nsGkAtoms::munderover_, // munderover
+   &nsGkAtoms::naturalnumbers_, // naturalnumbers
+   &nsGkAtoms::neq_, // neq
+   &nsGkAtoms::none, // none
+   &nsGkAtoms::_not, // not
+   &nsGkAtoms::notanumber_, // notanumber
+   &nsGkAtoms::note_, // note
+   &nsGkAtoms::notin_, // notin
+   &nsGkAtoms::notprsubset_, // notprsubset
+   &nsGkAtoms::notsubset_, // notsubset
+   &nsGkAtoms::_or, // or
+   &nsGkAtoms::otherwise, // otherwise
+   &nsGkAtoms::outerproduct_, // outerproduct
+   &nsGkAtoms::partialdiff_, // partialdiff
+   &nsGkAtoms::pi_, // pi
+   &nsGkAtoms::piece_, // piece
+   &nsGkAtoms::piecewise_, // piecewise
+   &nsGkAtoms::plus_, // plus
+   &nsGkAtoms::power_, // power
+   &nsGkAtoms::primes_, // primes
+   &nsGkAtoms::product_, // product
+   &nsGkAtoms::prsubset_, // prsubset
+   &nsGkAtoms::quotient_, // quotient
+   &nsGkAtoms::rationals_, // rationals
+   &nsGkAtoms::real_, // real
+   &nsGkAtoms::reals_, // reals
+   &nsGkAtoms::reln_, // reln
+   &nsGkAtoms::rem, // rem
+   &nsGkAtoms::root_, // root
+   &nsGkAtoms::scalarproduct_, // scalarproduct
+   &nsGkAtoms::sdev_, // sdev
+   &nsGkAtoms::sec_, // sec
+   &nsGkAtoms::sech_, // sech
+   &nsGkAtoms::selector_, // selector
+   &nsGkAtoms::semantics_, // semantics
+   &nsGkAtoms::sep_, // sep
+   &nsGkAtoms::set_, // set
+   &nsGkAtoms::setdiff_, // setdiff
+   &nsGkAtoms::share_, // share
+   &nsGkAtoms::sin_, // sin
+   &nsGkAtoms::sinh_, // sinh
+   &nsGkAtoms::subset_, // subset
+   &nsGkAtoms::sum, // sum
+   &nsGkAtoms::tan_, // tan
+   &nsGkAtoms::tanh_, // tanh
+   &nsGkAtoms::tendsto_, // tendsto
+   &nsGkAtoms::times_, // times
+   &nsGkAtoms::transpose_, // transpose
+   &nsGkAtoms::_true, // true
+   &nsGkAtoms::union_, // union
+   &nsGkAtoms::uplimit_, // uplimit
+   &nsGkAtoms::variance_, // variance
+   &nsGkAtoms::vector_, // vector
+   &nsGkAtoms::vectorproduct_, // vectorproduct
+   &nsGkAtoms::xor_, // xor
+  nsnull
+};
+
+nsIAtom** const kAttributesMathML[] = {
+   &nsGkAtoms::accent_, // accent
+   &nsGkAtoms::accentunder_, // accentunder
+   &nsGkAtoms::actiontype_, // actiontype
+   &nsGkAtoms::align, // align
+   &nsGkAtoms::alignmentscope_, // alignmentscope
+   &nsGkAtoms::alt, // alt
+   &nsGkAtoms::altimg_, // altimg
+   &nsGkAtoms::altimg_height_, // altimg-height
+   &nsGkAtoms::altimg_valign_, // altimg-valign
+   &nsGkAtoms::altimg_width_, // altimg-width
+   &nsGkAtoms::background, // background
+   &nsGkAtoms::base, // base
+   &nsGkAtoms::bevelled_, // bevelled
+   &nsGkAtoms::cd_, // cd
+   &nsGkAtoms::cdgroup_, // cdgroup
+   &nsGkAtoms::charalign_, // charalign
+   &nsGkAtoms::close, // close
+   &nsGkAtoms::closure_, // closure
+   &nsGkAtoms::color, // color
+   &nsGkAtoms::columnalign_, // columnalign
+   &nsGkAtoms::columnalignment_, // columnalignment
+   &nsGkAtoms::columnlines_, // columnlines
+   &nsGkAtoms::columnspacing_, // columnspacing
+   &nsGkAtoms::columnspan_, // columnspan
+   &nsGkAtoms::columnwidth_, // columnwidth
+   &nsGkAtoms::crossout_, // crossout
+   &nsGkAtoms::decimalpoint_, // decimalpoint
+   &nsGkAtoms::definitionURL_, // definitionURL
+   &nsGkAtoms::denomalign_, // denomalign
+   &nsGkAtoms::depth_, // depth
+   &nsGkAtoms::dir, // dir
+   &nsGkAtoms::display, // display
+   &nsGkAtoms::displaystyle_, // displaystyle
+   &nsGkAtoms::edge_, // edge
+   &nsGkAtoms::encoding, // encoding
+   &nsGkAtoms::equalcolumns_, // equalcolumns
+   &nsGkAtoms::equalrows_, // equalrows
+   &nsGkAtoms::fence_, // fence
+   &nsGkAtoms::fontfamily_, // fontfamily
+   &nsGkAtoms::fontsize_, // fontsize
+   &nsGkAtoms::fontstyle_, // fontstyle
+   &nsGkAtoms::fontweight_, // fontweight
+   &nsGkAtoms::form, // form
+   &nsGkAtoms::frame, // frame
+   &nsGkAtoms::framespacing_, // framespacing
+   &nsGkAtoms::groupalign_, // groupalign
+   &nsGkAtoms::height, // height
+   &nsGkAtoms::href, // href
+   &nsGkAtoms::id, // id
+   &nsGkAtoms::indentalign_, // indentalign
+   &nsGkAtoms::indentalignfirst_, // indentalignfirst
+   &nsGkAtoms::indentalignlast_, // indentalignlast
+   &nsGkAtoms::indentshift_, // indentshift
+   &nsGkAtoms::indentshiftfirst_, // indentshiftfirst
+   &nsGkAtoms::indenttarget_, // indenttarget
+   &nsGkAtoms::index, // index
+   &nsGkAtoms::integer, // integer
+   &nsGkAtoms::largeop_, // largeop
+   &nsGkAtoms::length, // length
+   &nsGkAtoms::linebreak_, // linebreak
+   &nsGkAtoms::linebreakmultchar_, // linebreakmultchar
+   &nsGkAtoms::linebreakstyle_, // linebreakstyle
+   &nsGkAtoms::linethickness_, // linethickness
+   &nsGkAtoms::location_, // location
+   &nsGkAtoms::longdivstyle_, // longdivstyle
+   &nsGkAtoms::lquote_, // lquote
+   &nsGkAtoms::lspace_, // lspace
+   &nsGkAtoms::ltr, // ltr
+   &nsGkAtoms::mathbackground_, // mathbackground
+   &nsGkAtoms::mathcolor_, // mathcolor
+   &nsGkAtoms::mathsize_, // mathsize
+   &nsGkAtoms::mathvariant_, // mathvariant
+   &nsGkAtoms::maxsize_, // maxsize
+   &nsGkAtoms::mediummathspace_, // mediummathspace
+   &nsGkAtoms::minlabelspacing_, // minlabelspacing
+   &nsGkAtoms::minsize_, // minsize
+   &nsGkAtoms::monospaced_, // monospaced
+   &nsGkAtoms::movablelimits_, // movablelimits
+   &nsGkAtoms::msgroup_, // msgroup
+   &nsGkAtoms::name, // name
+   &nsGkAtoms::negativemediummathspace_, // negativemediummathspace
+   &nsGkAtoms::negativethickmathspace_, // negativethickmathspace
+   &nsGkAtoms::negativethinmathspace_, // negativethinmathspace
+   &nsGkAtoms::negativeverythickmathspace_, // negativeverythickmathspace
+   &nsGkAtoms::negativeverythinmathspace_, // negativeverythinmathspace
+   &nsGkAtoms::negativeveryverythickmathspace_, // negativeveryverythickmathspace
+   &nsGkAtoms::negativeveryverythinmathspace_, // negativeveryverythinmathspace
+   &nsGkAtoms::newline, // newline
+   &nsGkAtoms::notation_, // notation
+   &nsGkAtoms::numalign_, // numalign
+   &nsGkAtoms::number, // number
+   &nsGkAtoms::open, // open
+   &nsGkAtoms::order, // order
+   &nsGkAtoms::other_, // other
+   &nsGkAtoms::overflow, // overflow
+   &nsGkAtoms::position, // position
+   &nsGkAtoms::role, // role
+   &nsGkAtoms::rowalign_, // rowalign
+   &nsGkAtoms::rowlines_, // rowlines
+   &nsGkAtoms::rowspacing_, // rowspacing
+   &nsGkAtoms::rowspan, // rowspan
+   &nsGkAtoms::rquote_, // rquote
+   &nsGkAtoms::rspace_, // rspace
+   &nsGkAtoms::schemaLocation_, // schemaLocation
+   &nsGkAtoms::scriptlevel_, // scriptlevel
+   &nsGkAtoms::scriptminsize_, // scriptminsize
+   &nsGkAtoms::scriptsize_, // scriptsize
+   &nsGkAtoms::scriptsizemultiplier_, // scriptsizemultiplier
+   &nsGkAtoms::selection_, // selection
+   &nsGkAtoms::separator_, // separator
+   &nsGkAtoms::separators_, // separators
+   &nsGkAtoms::shift_, // shift
+   &nsGkAtoms::side_, // side
+   &nsGkAtoms::src, // src
+   &nsGkAtoms::stackalign_, // stackalign
+   &nsGkAtoms::stretchy_, // stretchy
+   &nsGkAtoms::subscriptshift_, // subscriptshift
+   &nsGkAtoms::superscriptshift_, // superscriptshift
+   &nsGkAtoms::symmetric_, // symmetric
+   &nsGkAtoms::thickmathspace_, // thickmathspace
+   &nsGkAtoms::thinmathspace_, // thinmathspace
+   &nsGkAtoms::type, // type
+   &nsGkAtoms::verythickmathspace_, // verythickmathspace
+   &nsGkAtoms::verythinmathspace_, // verythinmathspace
+   &nsGkAtoms::veryverythickmathspace_, // veryverythickmathspace
+   &nsGkAtoms::veryverythinmathspace_, // veryverythinmathspace
+   &nsGkAtoms::voffset_, // voffset
+   &nsGkAtoms::width, // width
+   &nsGkAtoms::xref_, // xref
+  nsnull
+};
+
+nsIAtom** const kURLAttributesMathML[] = {
+  &nsGkAtoms::href,
+  &nsGkAtoms::src,
+  &nsGkAtoms::definitionURL_,
+  nsnull
+};
+
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsHTML = nsnull;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesHTML = nsnull;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsSVG = nsnull;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesSVG = nsnull;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sElementsMathML = nsnull;
+nsTHashtable<nsISupportsHashKey>* nsTreeSanitizer::sAttributesMathML = nsnull;
+nsIPrincipal* nsTreeSanitizer::sNullPrincipal = nsnull;
+
+nsTreeSanitizer::nsTreeSanitizer(PRBool aAllowStyles, PRBool aAllowComments)
+ : mAllowStyles(aAllowStyles)
+ , mAllowComments(aAllowComments)
+{
+  if (!sElementsHTML) {
+    // Initialize lazily to avoid having to initialize at all if the user
+    // doesn't paste HTML or load feeds.
+    InitializeStatics();
+  }
+}
+
+PRBool
+nsTreeSanitizer::MustFlatten(PRInt32 aNamespace, nsIAtom* aLocal)
+{
+  if (aNamespace == kNameSpaceID_XHTML) {
+    return !sElementsHTML->GetEntry(aLocal);
+  }
+  if (aNamespace == kNameSpaceID_SVG) {
+    return !sElementsSVG->GetEntry(aLocal);
+  }
+  if (aNamespace == kNameSpaceID_MathML) {
+    return !sElementsMathML->GetEntry(aLocal);
+  }
+  return PR_TRUE;
+}
+
+PRBool
+nsTreeSanitizer::IsURL(nsIAtom*** aURLs, nsIAtom* aLocalName)
+{
+  nsIAtom** atomPtrPtr;
+  while ((atomPtrPtr = *aURLs)) {
+    if (*atomPtrPtr == aLocalName) {
+      return PR_TRUE;
+    }
+    ++aURLs;
+  }
+  return PR_FALSE;
+}
+
+PRBool
+nsTreeSanitizer::MustPrune(PRInt32 aNamespace,
+                           nsIAtom* aLocal,
+                           mozilla::dom::Element* aElement)
+{
+  // To avoid attacks where a MathML script becomes something that gets
+  // serialized in a way that it parses back as an HTML script, let's just
+  // drop elements with the local name 'script' regardless of namespace.
+  if (nsGkAtoms::script == aLocal) {
+    return PR_TRUE;
+  }
+  if (aNamespace == kNameSpaceID_XHTML) {
+    if (nsGkAtoms::title == aLocal) {
+      // emulate the quirks of the old parser
+      return PR_TRUE;
+    }
+    if ((nsGkAtoms::meta == aLocal || nsGkAtoms::link == aLocal) &&
+        !(aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
+          aElement->HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope))) {
+      // emulate old behavior for non-Microdata <meta> and <link> presumably
+      // in <head>. <meta> and <link> are whitelisted in order to avoid
+      // corrupting Microdata when they appear in <body>. Note that
+      // SanitizeAttributes() will remove the rel attribute from <link> and
+      // the name attribute from <meta>.
+      return PR_TRUE;
+    }
+  }
+  if (mAllowStyles) {
+    if (nsGkAtoms::style == aLocal && !(aNamespace == kNameSpaceID_XHTML
+        || aNamespace == kNameSpaceID_SVG)) {
+      return PR_TRUE;
+    }
+    return PR_FALSE;
+  }
+  if (nsGkAtoms::style == aLocal) {
+    return PR_TRUE;
+  }
+  return PR_FALSE;
+}
+
+PRBool
+nsTreeSanitizer::SanitizeStyleRule(mozilla::css::StyleRule *aRule,
+                                   nsAutoString &aRuleText)
+{
+  PRBool didSanitize = PR_FALSE;
+  aRuleText.Truncate();
+  mozilla::css::Declaration* style = aRule->GetDeclaration();
+  if (style) {
+    didSanitize = style->HasProperty(eCSSProperty_binding);
+    style->RemoveProperty(eCSSProperty_binding);
+    style->ToString(aRuleText);
+  }
+  return didSanitize;
+}
+
+PRBool
+nsTreeSanitizer::SanitizeStyleSheet(const nsAString& aOriginal,
+                                    nsAString& aSanitized,
+                                    nsIDocument* aDocument,
+                                    nsIURI* aBaseURI)
+{
+  nsresult rv;
+  aSanitized.Truncate();
+  // aSanitized will hold the permitted CSS text.
+  // -moz-binding is blacklisted.
+  PRBool didSanitize = PR_FALSE;
+  // Create a sheet to hold the parsed CSS
+  nsRefPtr<nsCSSStyleSheet> sheet;
+  rv = NS_NewCSSStyleSheet(getter_AddRefs(sheet));
+  NS_ENSURE_SUCCESS(rv, PR_TRUE);
+  sheet->SetURIs(aDocument->GetDocumentURI(), nsnull, aBaseURI);
+  sheet->SetPrincipal(aDocument->NodePrincipal());
+  // Create the CSS parser, and parse the CSS text.
+  nsCSSParser parser(nsnull, sheet);
+  rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
+                         aDocument->NodePrincipal(), 0, PR_FALSE);
+  NS_ENSURE_SUCCESS(rv, PR_TRUE);
+  // Mark the sheet as complete.
+  NS_ABORT_IF_FALSE(!sheet->IsModified(),
+      "should not get marked modified during parsing");
+  sheet->SetComplete();
+  // Loop through all the rules found in the CSS text
+  PRInt32 ruleCount = sheet->StyleRuleCount();
+  for (PRInt32 i = 0; i < ruleCount; ++i) {
+    nsRefPtr<mozilla::css::Rule> rule;
+    rv = sheet->GetStyleRuleAt(i, *getter_AddRefs(rule));
+    if (NS_FAILED(rv))
+      continue; NS_ASSERTION(rule, "We should have a rule by now");
+    switch (rule->GetType()) {
+      default:
+        didSanitize = PR_TRUE;
+        // Ignore these rule types.
+        break;
+      case mozilla::css::Rule::NAMESPACE_RULE:
+      case mozilla::css::Rule::FONT_FACE_RULE: {
+        // Append @namespace and @font-face rules verbatim.
+        nsAutoString cssText;
+        nsCOMPtr<nsIDOMCSSRule> styleRule = do_QueryInterface(rule);
+        if (styleRule) {
+          rv = styleRule->GetCssText(cssText);
+          if (NS_SUCCEEDED(rv)) {
+            aSanitized.Append(cssText);
+          }
+        }
+        break;
+      }
+      case mozilla::css::Rule::STYLE_RULE: {
+        // For style rules, we will just look for and remove the
+        // -moz-binding properties.
+        nsRefPtr<mozilla::css::StyleRule> styleRule = do_QueryObject(rule);
+        NS_ASSERTION(styleRule, "Must be a style rule");
+        nsAutoString decl;
+        PRBool sanitized = SanitizeStyleRule(styleRule, decl);
+        didSanitize = sanitized || didSanitize;
+        if (!sanitized) {
+          styleRule->GetCssText(decl);
+        }
+        aSanitized.Append(decl);
+      }
+    }
+  }
+  return didSanitize;
+}
+
+void
+nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
+                                    nsTHashtable<nsISupportsHashKey>* aAllowed,
+                                    nsIAtom*** aURLs,
+                                    PRBool aAllowXLink,
+                                    PRBool aAllowStyle,
+                                    PRBool aAllowDangerousSrc)
+{
+  PRUint32 ac = aElement->GetAttrCount();
+
+  nsresult rv;
+
+  for (PRInt32 i = ac - 1; i >= 0; --i) {
+    rv = NS_OK;
+    const nsAttrName* attrName = aElement->GetAttrNameAt(i);
+    PRInt32 attrNs = attrName->NamespaceID();
+    nsIAtom* attrLocal = attrName->Atom();
+
+    if (kNameSpaceID_None == attrNs) {
+      if (aAllowStyle && nsGkAtoms::style == attrLocal) {
+        nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
+        nsIDocument* document = aElement->GetOwnerDoc();
+        // Pass the CSS Loader object to the parser, to allow parser error
+        // reports to include the outer window ID.
+        nsCSSParser parser(document->CSSLoader());
+        nsRefPtr<mozilla::css::StyleRule> rule;
+        nsAutoString value;
+        aElement->GetAttr(attrNs, attrLocal, value);
+        rv = parser.ParseStyleAttribute(value,
+                                        document->GetDocumentURI(),
+                                        baseURI,
+                                        document->NodePrincipal(),
+                                        getter_AddRefs(rule));
+        if (NS_SUCCEEDED(rv)) {
+          nsAutoString cleanValue;
+          if (SanitizeStyleRule(rule, cleanValue)) {
+            aElement->SetAttr(kNameSpaceID_None,
+                              nsGkAtoms::style,
+                              cleanValue,
+                              PR_FALSE);
+          }
+        }
+        continue;
+      }
+      if (aAllowDangerousSrc && nsGkAtoms::src == attrLocal) {
+        continue;
+      }
+      if (IsURL(aURLs, attrLocal)) {
+        SanitizeURL(aElement, attrNs, attrLocal);
+        continue;
+      }
+      if (aAllowed->GetEntry(attrLocal) &&
+          !(attrLocal == nsGkAtoms::rel &&
+            aElement->IsHTML(nsGkAtoms::link)) &&
+          !(attrLocal == nsGkAtoms::name &&
+            aElement->IsHTML(nsGkAtoms::meta))) {
+        // name="" and rel="" are whitelisted, but treat them as blacklisted
+        // for <meta name> and <link rel> to avoid document-wide metadata
+        // or styling overrides with non-conforming <meta name itemprop> or
+        // <link rel itemprop>
+        continue;
+      }
+      const PRUnichar* localStr = attrLocal->GetUTF16String();
+      // Allow underscore to cater to the MCE editor library.
+      // Allow data-* on SVG and MathML, too, as a forward-compat measure.
+      if (*localStr == '_' || (attrLocal->GetLength() > 5 && localStr[0] == 'd'
+          && localStr[1] == 'a' && localStr[2] == 't' && localStr[3] == 'a'
+          && localStr[4] == '-')) {
+        continue;
+      }
+      // else not allowed
+    } else if (kNameSpaceID_XML == attrNs) {
+      if (nsGkAtoms::base == attrLocal) {
+        SanitizeURL(aElement, attrNs, attrLocal);
+        continue;
+      }
+      if (nsGkAtoms::lang == attrLocal || nsGkAtoms::space == attrLocal) {
+        continue;
+      }
+      // else not allowed
+    } else if (aAllowXLink && kNameSpaceID_XLink == attrNs) {
+      if (nsGkAtoms::href == attrLocal) {
+        SanitizeURL(aElement, attrNs, attrLocal);
+        continue;
+      }
+      if (nsGkAtoms::type == attrLocal || nsGkAtoms::title == attrLocal
+          || nsGkAtoms::show == attrLocal || nsGkAtoms::actuate == attrLocal) {
+        continue;
+      }
+      // else not allowed
+    }
+    aElement->UnsetAttr(kNameSpaceID_None, attrLocal, PR_FALSE);
+    // in case the attribute removal shuffled the attribute order, start the
+    // loop again.
+    --ac;
+    i = ac; // i will be decremented immediately thanks to the for loop
+  }
+
+  // If we've got HTML audio or video, add the controls attribute, because
+  // otherwise the content is unplayable with scripts removed.
+  if (aElement->IsHTML(nsGkAtoms::video) ||
+      aElement->IsHTML(nsGkAtoms::audio)) {
+    aElement->SetAttr(kNameSpaceID_None,
+                      nsGkAtoms::controls,
+                      EmptyString(),
+                      PR_FALSE);
+  }
+}
+
+void
+nsTreeSanitizer::SanitizeURL(mozilla::dom::Element* aElement,
+                             PRInt32 aNamespace,
+                             nsIAtom* aLocalName)
+{
+  nsAutoString value;
+  aElement->GetAttr(aNamespace, aLocalName, value);
+
+  // Get value and remove mandatory quotes
+  static const char* kWhitespace = "\n\r\t\b";
+  const nsAString& v =
+    nsContentUtils::TrimCharsInSet(kWhitespace, value);
+
+  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
+  PRUint32 flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
+
+  nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURI();
+  nsCOMPtr<nsIURI> attrURI;
+  nsresult rv = NS_NewURI(getter_AddRefs(attrURI), v, nsnull, baseURI);
+  if (NS_SUCCEEDED(rv)) {
+    rv = secMan->CheckLoadURIWithPrincipal(sNullPrincipal, attrURI, flags);
+  }
+  if (NS_FAILED(rv)) {
+    aElement->UnsetAttr(aNamespace, aLocalName, PR_FALSE);
+  }
+}
+
+void
+nsTreeSanitizer::Sanitize(nsIContent* aFragment) {
+  // If you want to relax these preconditions, be sure to check the code in
+  // here that notifies / does not notify or that fires mutation events if
+  // in tree.
+  NS_PRECONDITION(aFragment->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT),
+      "Argument was not DOM fragment.");
+  NS_PRECONDITION(!aFragment->IsInDoc(), "The fragment is in doc?");
+
+  nsIContent* node = aFragment->GetFirstChild();
+  while (node) {
+    if (node->IsElement()) {
+      mozilla::dom::Element* elt = node->AsElement();
+      nsINodeInfo* nodeInfo = node->NodeInfo();
+      nsIAtom* localName = nodeInfo->NameAtom();
+      PRInt32 ns = nodeInfo->NamespaceID();
+
+      if (MustPrune(ns, localName, elt)) {
+        nsIContent* next = node->GetNextNonChildNode(aFragment);
+        node->GetParent()->RemoveChild(node);
+        node = next;
+        continue;
+      }
+      if (nsGkAtoms::style == localName) {
+        // If styles aren't allowed, style elements got pruned above. Even
+        // if styles are allowed, non-HTML, non-SVG style elements got pruned
+        // above.
+        NS_ASSERTION(ns == kNameSpaceID_XHTML || ns == kNameSpaceID_SVG,
+            "Should have only HTML or SVG here!");
+        nsAutoString styleText;
+        nsContentUtils::GetNodeTextContent(node, PR_FALSE, styleText);
+        nsAutoString sanitizedStyle;
+        nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
+        if (SanitizeStyleSheet(styleText,
+                               sanitizedStyle,
+                               aFragment->GetOwnerDoc(),
+                               baseURI)) {
+          nsContentUtils::SetNodeTextContent(node, sanitizedStyle, PR_TRUE);
+        } else {
+          // If the node had non-text child nodes, this operation zaps those.
+          nsContentUtils::SetNodeTextContent(node, styleText, PR_TRUE);
+        }
+        if (ns == kNameSpaceID_XHTML) {
+          SanitizeAttributes(elt,
+                             sAttributesHTML,
+                             (nsIAtom***)kURLAttributesHTML,
+                             PR_FALSE,
+                             mAllowStyles,
+                             PR_FALSE);
+        } else {
+          SanitizeAttributes(elt,
+                             sAttributesSVG,
+                             (nsIAtom***)kURLAttributesSVG,
+                             PR_TRUE,
+                             mAllowStyles,
+                             PR_FALSE);
+        }
+        node = node->GetNextNonChildNode(aFragment);
+        continue;
+      }
+      if (MustFlatten(ns, localName)) {
+        nsIContent* next = node->GetNextNode(aFragment);
+        nsIContent* parent = node->GetParent();
+        nsCOMPtr<nsIContent> child; // Must keep the child alive during move
+        nsresult rv;
+        while ((child = node->GetFirstChild())) {
+          parent->InsertBefore(child, node, &rv);
+          if (NS_FAILED(rv)) {
+            break;
+          }
+        }
+        parent->RemoveChild(node);
+        node = next;
+        continue;
+      }
+      NS_ASSERTION(ns == kNameSpaceID_XHTML ||
+                   ns == kNameSpaceID_SVG ||
+                   ns == kNameSpaceID_MathML,
+          "Should have only HTML, MathML or SVG here!");
+      if (ns == kNameSpaceID_XHTML) {
+        SanitizeAttributes(elt,
+                           sAttributesHTML,
+                           (nsIAtom***)kURLAttributesHTML,
+                           PR_FALSE, mAllowStyles,
+                           (nsGkAtoms::img == localName));
+      } else if (ns == kNameSpaceID_SVG) {
+        SanitizeAttributes(elt,
+                           sAttributesSVG,
+                           (nsIAtom***)kURLAttributesSVG,
+                           PR_TRUE,
+                           mAllowStyles,
+                           PR_FALSE);
+      } else {
+        SanitizeAttributes(elt,
+                           sAttributesMathML,
+                           (nsIAtom***)kURLAttributesMathML,
+                           PR_TRUE,
+                           PR_FALSE,
+                           PR_FALSE);
+      }
+      node = node->GetNextNode(aFragment);
+      continue;
+    }
+    NS_ASSERTION(!node->GetFirstChild(), "How come non-element node had kids?");
+    nsIContent* next = node->GetNextNonChildNode(aFragment);
+    if (!mAllowComments && node->IsNodeOfType(nsINode::eCOMMENT)) {
+      node->GetParent()->RemoveChild(node);
+    }
+    node = next;
+  }
+}
+
+void
+nsTreeSanitizer::InitializeStatics()
+{
+  NS_PRECONDITION(!sElementsHTML, "Initializing a second time.");
+
+  sElementsHTML = new nsTHashtable<nsISupportsHashKey> ();
+  sElementsHTML->Init(NS_ARRAY_LENGTH(kElementsHTML));
+  for (PRUint32 i = 0; kElementsHTML[i]; i++) {
+    sElementsHTML->PutEntry(*kElementsHTML[i]);
+  }
+
+  sAttributesHTML = new nsTHashtable<nsISupportsHashKey> ();
+  sAttributesHTML->Init(NS_ARRAY_LENGTH(kAttributesHTML));
+  for (PRUint32 i = 0; kAttributesHTML[i]; i++) {
+    sAttributesHTML->PutEntry(*kAttributesHTML[i]);
+  }
+
+  sElementsSVG = new nsTHashtable<nsISupportsHashKey> ();
+  sElementsSVG->Init(NS_ARRAY_LENGTH(kElementsSVG));
+  for (PRUint32 i = 0; kElementsSVG[i]; i++) {
+    sElementsSVG->PutEntry(*kElementsSVG[i]);
+  }
+
+  sAttributesSVG = new nsTHashtable<nsISupportsHashKey> ();
+  sAttributesSVG->Init(NS_ARRAY_LENGTH(kAttributesSVG));
+  for (PRUint32 i = 0; kAttributesSVG[i]; i++) {
+    sAttributesSVG->PutEntry(*kAttributesSVG[i]);
+  }
+
+  sElementsMathML = new nsTHashtable<nsISupportsHashKey> ();
+  sElementsMathML->Init(NS_ARRAY_LENGTH(kElementsMathML));
+  for (PRUint32 i = 0; kElementsMathML[i]; i++) {
+    sElementsMathML->PutEntry(*kElementsMathML[i]);
+  }
+
+  sAttributesMathML = new nsTHashtable<nsISupportsHashKey> ();
+  sAttributesMathML->Init(NS_ARRAY_LENGTH(kAttributesMathML));
+  for (PRUint32 i = 0; kAttributesMathML[i]; i++) {
+    sAttributesMathML->PutEntry(*kAttributesMathML[i]);
+  }
+
+  nsCOMPtr<nsIPrincipal> principal =
+      do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID);
+  principal.forget(&sNullPrincipal);
+}
+
+void
+nsTreeSanitizer::ReleaseStatics()
+{
+  delete sElementsHTML;
+  sElementsHTML = nsnull;
+
+  delete sAttributesHTML;
+  sAttributesHTML = nsnull;
+
+  delete sElementsSVG;
+  sElementsSVG = nsnull;
+
+  delete sAttributesSVG;
+  sAttributesSVG = nsnull;
+
+  delete sElementsMathML;
+  sElementsMathML = nsnull;
+
+  delete sAttributesMathML;
+  sAttributesMathML = nsnull;
+
+  NS_IF_RELEASE(sNullPrincipal);
+}
--- a/content/html/document/src/nsHTMLFragmentContentSink.cpp
+++ b/content/html/document/src/nsHTMLFragmentContentSink.cpp
@@ -773,512 +773,8 @@ nsHTMLFragmentContentSink::AddAttributes
       // Add attribute to content
       aContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
     }
   }
 
   return NS_OK;
 }
 
-// nsHTMLParanoidFragmentSink
-
-// Find the whitelist of allowed elements and attributes in
-// nsContentSink.h We share it with nsHTMLParanoidFragmentSink
-
-class nsHTMLParanoidFragmentSink : public nsHTMLFragmentContentSink,
-                                   public nsIParanoidFragmentContentSink
-{
-public:
-  nsHTMLParanoidFragmentSink(PRBool aAllContent = PR_FALSE);
-
-  static nsresult Init();
-  static void Cleanup();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  NS_IMETHOD OpenContainer(const nsIParserNode& aNode);
-  NS_IMETHOD CloseContainer(const nsHTMLTag aTag);
-  NS_IMETHOD AddLeaf(const nsIParserNode& aNode);
-  NS_IMETHOD AddComment(const nsIParserNode& aNode);
-  NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode);
-
-  nsresult AddAttributes(const nsIParserNode& aNode,
-                         nsIContent* aContent);
-
-  // nsIParanoidFragmentContentSink
-  virtual void AllowStyles();
-  virtual void AllowComments();
-
-protected:
-  nsresult NameFromType(const nsHTMLTag aTag,
-                        nsIAtom **aResult);
-
-  nsresult NameFromNode(const nsIParserNode& aNode,
-                        nsIAtom **aResult);
-
-  // The return value will be true if we have sanitized the rule
-  PRBool SanitizeStyleRule(css::StyleRule *aRule, nsAutoString &aRuleText);
-
-  PRPackedBool mSkip; // used when we descend into <style> or <script>
-  PRPackedBool mProcessStyle; // used when style is explicitly white-listed
-  PRPackedBool mInStyle; // whether we're inside a style element
-  PRPackedBool mProcessComments; // used when comments are allowed
-
-  nsCOMPtr<nsIPrincipal> mNullPrincipal;
-
-  // Use nsTHashTable as a hash set for our whitelists
-  static nsTHashtable<nsISupportsHashKey>* sAllowedTags;
-  static nsTHashtable<nsISupportsHashKey>* sAllowedAttributes;
-};
-
-nsTHashtable<nsISupportsHashKey>* nsHTMLParanoidFragmentSink::sAllowedTags;
-nsTHashtable<nsISupportsHashKey>* nsHTMLParanoidFragmentSink::sAllowedAttributes;
-
-nsHTMLParanoidFragmentSink::nsHTMLParanoidFragmentSink(PRBool aAllContent):
-  nsHTMLFragmentContentSink(aAllContent), mSkip(PR_FALSE),
-  mProcessStyle(PR_FALSE), mInStyle(PR_FALSE), mProcessComments(PR_FALSE)
-{
-}
-
-nsresult
-nsHTMLParanoidFragmentSink::Init()
-{
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  if (sAllowedTags) {
-    return NS_OK;
-  }
-
-  sAllowedTags = new nsTHashtable<nsISupportsHashKey>();
-  if (sAllowedTags) {
-    rv = sAllowedTags->Init(80);
-    for (PRUint32 i = 0; kDefaultAllowedTags[i] && NS_SUCCEEDED(rv); i++) {
-      if (!sAllowedTags->PutEntry(*kDefaultAllowedTags[i])) {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-  }
-
-  sAllowedAttributes = new nsTHashtable<nsISupportsHashKey>();
-  if (sAllowedAttributes && NS_SUCCEEDED(rv)) {
-    rv = sAllowedAttributes->Init(80);
-    for (PRUint32 i = 0;
-         kDefaultAllowedAttributes[i] && NS_SUCCEEDED(rv); i++) {
-      if (!sAllowedAttributes->PutEntry(*kDefaultAllowedAttributes[i])) {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-  }
-
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to populate whitelist hash sets");
-    Cleanup();
-    return rv; 
-  }
-
-  return rv;
-}
-
-void
-nsHTMLParanoidFragmentSink::Cleanup()
-{
-  if (sAllowedTags) {
-    delete sAllowedTags;
-    sAllowedTags = nsnull;
-  }
-  
-  if (sAllowedAttributes) {
-    delete sAllowedAttributes;
-    sAllowedAttributes = nsnull;
-  }
-}
-
-nsresult
-NS_NewHTMLParanoidFragmentSink(nsIFragmentContentSink** aResult)
-{
-  nsresult rv = nsHTMLParanoidFragmentSink::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsHTMLParanoidFragmentSink* it = new nsHTMLParanoidFragmentSink();
-  NS_ADDREF(*aResult = it);
-  
-  return NS_OK;
-}
-
-nsresult
-NS_NewHTMLParanoidFragmentSink2(nsIFragmentContentSink** aResult)
-{
-  nsHTMLParanoidFragmentSink* it = new nsHTMLParanoidFragmentSink(PR_TRUE);
-  if (!it) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  nsresult rv = nsHTMLParanoidFragmentSink::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ADDREF(*aResult = it);
-  
-  return NS_OK;
-}
-
-void
-NS_HTMLParanoidFragmentSinkShutdown()
-{
-  nsHTMLParanoidFragmentSink::Cleanup();
-}
-
-NS_IMPL_ISUPPORTS_INHERITED1(nsHTMLParanoidFragmentSink, nsHTMLFragmentContentSink, nsIParanoidFragmentContentSink)
-
-nsresult
-nsHTMLParanoidFragmentSink::NameFromType(const nsHTMLTag aTag,
-                                         nsIAtom **aResult)
-{
-  nsIParserService* parserService = nsContentUtils::GetParserService();
-  if (!parserService) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  NS_IF_ADDREF(*aResult = parserService->HTMLIdToAtomTag(aTag));
-  
-  return NS_OK;
-}
-
-nsresult
-nsHTMLParanoidFragmentSink::NameFromNode(const nsIParserNode& aNode,
-                                         nsIAtom **aResult)
-{
-  nsresult rv;
-  eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
-  
-  *aResult = nsnull;
-  if (type == eHTMLTag_userdefined) {
-    *aResult = NS_NewAtom(aNode.GetText());
-  } else {
-    rv = NameFromType(type, aResult);
-  }
-  return rv;
-}
-
-void
-nsHTMLParanoidFragmentSink::AllowStyles()
-{
-  mProcessStyle = PR_TRUE;
-}
-
-void
-nsHTMLParanoidFragmentSink::AllowComments()
-{
-  mProcessComments = PR_TRUE;
-}
-
-// nsHTMLFragmentContentSink
-
-nsresult
-nsHTMLParanoidFragmentSink::AddAttributes(const nsIParserNode& aNode,
-                                          nsIContent* aContent)
-{
-  PRInt32 ac = aNode.GetAttributeCount();
-
-  if (ac == 0) {
-    return NS_OK;
-  }
-
-  nsAutoString k;
-  nsHTMLTag nodeType = nsHTMLTag(aNode.GetNodeType());
-
-  nsresult rv;
-  // use this to check for safe URIs in the few attributes that allow them
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  PRUint32 flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
-  nsCOMPtr<nsIURI> baseURI;
-  if (!mNullPrincipal) {
-      mNullPrincipal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  for (PRInt32 i = ac - 1; i >= 0; i--) {
-    rv = NS_OK;
-    nsContentUtils::ASCIIToLower(aNode.GetKeyAt(i), k);
-    nsCOMPtr<nsIAtom> keyAtom = do_GetAtom(k);
-
-    // Check if this is an allowed attribute, or a style attribute in case
-    // we've been asked to allow style attributes, or an HTML5 data-*
-    // attribute, or an attribute which begins with "_".
-    if ((!sAllowedAttributes || !sAllowedAttributes->GetEntry(keyAtom)) &&
-        (!mProcessStyle || keyAtom != nsGkAtoms::style) &&
-        !(StringBeginsWith(k, NS_LITERAL_STRING("data-")) ||
-          StringBeginsWith(k, NS_LITERAL_STRING("_")))) {
-      continue;
-    }
-
-    // Get value and remove mandatory quotes
-    static const char* kWhitespace = "\n\r\t\b";
-    const nsAString& v =
-      nsContentUtils::TrimCharsInSet(kWhitespace, aNode.GetValueAt(i));
-
-    // check the attributes we allow that contain URIs
-    // special case src attributes for img tags, because they can't
-    // run any dangerous code.
-    if (IsAttrURI(keyAtom) &&
-        !(nodeType == eHTMLTag_img && keyAtom == nsGkAtoms::src)) {
-      if (!baseURI) {
-        baseURI = aContent->GetBaseURI();
-      }
-      nsCOMPtr<nsIURI> attrURI;
-      rv = NS_NewURI(getter_AddRefs(attrURI), v, nsnull, baseURI);
-      if (NS_SUCCEEDED(rv)) {
-        rv = secMan->
-          CheckLoadURIWithPrincipal(mNullPrincipal, attrURI, flags);
-      }
-    }
-    
-    // skip to the next attribute if we encountered issues with the
-    // current value
-    if (NS_FAILED(rv)) {
-      continue;
-    }
-
-    // Filter unsafe stuff from style attributes if they're allowed
-    if (mProcessStyle && keyAtom == nsGkAtoms::style) {
-      if (!baseURI) {
-        baseURI = aContent->GetBaseURI();
-      }
-
-      // Pass the CSS Loader object to the parser, to allow parser error reports
-      // to include the outer window ID.
-      nsCSSParser parser(mTargetDocument->CSSLoader());
-      nsRefPtr<css::StyleRule> rule;
-      rv = parser.ParseStyleAttribute(aNode.GetValueAt(i),
-                                      mTargetDocument->GetDocumentURI(),
-                                      baseURI,
-                                      mTargetDocument->NodePrincipal(),
-                                      getter_AddRefs(rule));
-      if (NS_SUCCEEDED(rv)) {
-        nsAutoString cleanValue;
-        PRBool didSanitize = SanitizeStyleRule(rule, cleanValue);
-        if (didSanitize) {
-          aContent->SetAttr(kNameSpaceID_None, keyAtom, cleanValue, PR_FALSE);
-        } else {
-          aContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
-        }
-      } else {
-        // we couldn't sanitize the style attribute, ignore it
-        continue;
-      }
-    } else if (nodeType == eHTMLTag_a && keyAtom == nsGkAtoms::name) {
-      NS_ConvertUTF16toUTF8 cname(v);
-      NS_ConvertUTF8toUTF16 uv(nsUnescape(cname.BeginWriting()));
-      // Add attribute to content
-      aContent->SetAttr(kNameSpaceID_None, keyAtom, uv, PR_FALSE);
-    } else {
-      // Add attribute to content
-      aContent->SetAttr(kNameSpaceID_None, keyAtom, v, PR_FALSE);
-    }
-  }
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLParanoidFragmentSink::OpenContainer(const nsIParserNode& aNode)
-{
-  nsresult rv = NS_OK;
-  
-  // bail if it's a script or style (when we don't allow processing of stylesheets),
-  // or we're already inside one of those
-  eHTMLTags type = (eHTMLTags)aNode.GetNodeType();
-  if (type == eHTMLTag_script || (!mProcessStyle && type == eHTMLTag_style)) {
-    mSkip = PR_TRUE;
-    return rv;
-  }
-
-  nsCOMPtr<nsIAtom> name;
-  rv = NameFromNode(aNode, getter_AddRefs(name));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // not on whitelist
-  if (!sAllowedTags || !sAllowedTags->GetEntry(name)) {
-    // unless it's style, and we're allowing it
-    if (!mProcessStyle || name != nsGkAtoms::style) {
-      return NS_OK;
-    }
-  }
-
-  if (type == eHTMLTag_style) {
-    mInStyle = PR_TRUE;
-  }
-
-  return nsHTMLFragmentContentSink::OpenContainer(aNode);
-}
-
-NS_IMETHODIMP
-nsHTMLParanoidFragmentSink::CloseContainer(const nsHTMLTag aTag)
-{
-  nsresult rv = NS_OK;
-
-  if (mIgnoreNextCloseHead && aTag == eHTMLTag_head) {
-    mIgnoreNextCloseHead = PR_FALSE;
-    return NS_OK;
-  }
-  if (mSkip) {
-    mSkip = PR_FALSE;
-    return rv;
-  }
-
-  nsCOMPtr<nsIAtom> name;
-  rv = NameFromType(aTag, getter_AddRefs(name));
-  NS_ENSURE_SUCCESS(rv, rv);
-  
-  // not on whitelist
-  if (!sAllowedTags || !sAllowedTags->GetEntry(name)) {
-    // unless it's style, and we're allowing it
-    if (!mProcessStyle || name != nsGkAtoms::style) {
-      return NS_OK;
-    }
-  }
-
-  if (mInStyle && name == nsGkAtoms::style) {
-    mInStyle = PR_FALSE;
-
-    // Flush the text to make sure that the style text is complete.
-    FlushText();
-
-    // sanitizedStyleText will hold the permitted CSS text.
-    // We use a white-listing approach, so we explicitly allow
-    // the CSS style and font-face rule types.  We also clear
-    // -moz-binding CSS properties.
-    nsAutoString sanitizedStyleText;
-    nsIContent* style = GetCurrentContent();
-    if (style) {
-      PRBool didSanitize = PR_FALSE;
-      // styleText will hold the text inside the style element.
-      nsAutoString styleText;
-      nsContentUtils::GetNodeTextContent(style, PR_FALSE, styleText);
-      // Create a sheet to hold the parsed CSS
-      nsRefPtr<nsCSSStyleSheet> sheet;
-      rv = NS_NewCSSStyleSheet(getter_AddRefs(sheet));
-      if (NS_SUCCEEDED(rv)) {
-        nsCOMPtr<nsIURI> baseURI = style->GetBaseURI();
-        sheet->SetURIs(mTargetDocument->GetDocumentURI(), nsnull, baseURI);
-        sheet->SetPrincipal(mTargetDocument->NodePrincipal());
-        // Create the CSS parser, and parse the CSS text.
-        nsCSSParser parser(nsnull, sheet);
-        rv = parser.ParseSheet(styleText, mTargetDocument->GetDocumentURI(),
-                               baseURI, mTargetDocument->NodePrincipal(),
-                               0, PR_FALSE);
-        // Mark the sheet as complete.
-        if (NS_SUCCEEDED(rv)) {
-          NS_ABORT_IF_FALSE(!sheet->IsModified(),
-                            "should not get marked modified during parsing");
-          sheet->SetComplete();
-        }
-        if (NS_SUCCEEDED(rv)) {
-          // Loop through all the rules found in the CSS text
-          PRInt32 ruleCount = sheet->StyleRuleCount();
-          for (PRInt32 i = 0; i < ruleCount; ++i) {
-            nsRefPtr<css::Rule> rule;
-            rv = sheet->GetStyleRuleAt(i, *getter_AddRefs(rule));
-            if (NS_FAILED(rv))
-              continue;
-            NS_ASSERTION(rule, "We should have a rule by now");
-            switch (rule->GetType()) {
-            default:
-              didSanitize = PR_TRUE;
-              // Ignore these rule types.
-              break;
-            case css::Rule::NAMESPACE_RULE:
-            case css::Rule::FONT_FACE_RULE: {
-              // Append @namespace and @font-face rules verbatim.
-              nsAutoString cssText;
-              nsCOMPtr<nsIDOMCSSRule> styleRule = do_QueryInterface(rule);
-              if (styleRule) {
-                rv = styleRule->GetCssText(cssText);
-                if (NS_SUCCEEDED(rv)) {
-                  sanitizedStyleText.Append(cssText);
-                }
-              }
-              break;
-            }
-            case css::Rule::STYLE_RULE: {
-              // For style rules, we will just look for and remove the
-              // -moz-binding properties.
-              nsRefPtr<css::StyleRule> styleRule = do_QueryObject(rule);
-              NS_ASSERTION(styleRule, "Must be a style rule");
-              nsAutoString decl;
-              didSanitize = SanitizeStyleRule(styleRule, decl) || didSanitize;
-              styleRule->GetCssText(decl);
-              sanitizedStyleText.Append(decl);
-            }
-            }
-          }
-        }
-      }
-      if (didSanitize) {
-        // Replace the style element content with its sanitized style text
-        nsContentUtils::SetNodeTextContent(style, sanitizedStyleText, PR_TRUE);
-      }
-    }
-  }
-
-  return nsHTMLFragmentContentSink::CloseContainer(aTag);
-}
-
-PRBool
-nsHTMLParanoidFragmentSink::SanitizeStyleRule(css::StyleRule *aRule, nsAutoString &aRuleText)
-{
-  PRBool didSanitize = PR_FALSE;
-  aRuleText.Truncate();
-  css::Declaration *style = aRule->GetDeclaration();
-  if (style) {
-    didSanitize = style->HasProperty(eCSSProperty_binding);
-    style->RemoveProperty(eCSSProperty_binding);
-    style->ToString(aRuleText);
-  }
-  return didSanitize;
-}
-
-NS_IMETHODIMP
-nsHTMLParanoidFragmentSink::AddLeaf(const nsIParserNode& aNode)
-{
-  NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_NOT_INITIALIZED);
-  
-  nsresult rv = NS_OK;
-
-  // We need to explicitly skip adding leaf nodes in the paranoid sink,
-  // otherwise things like the textnode under <title> get appended to
-  // the fragment itself, and won't be popped off in CloseContainer.
-  if (mSkip || mIgnoreNextCloseHead) {
-    return rv;
-  }
-  
-  if (aNode.GetTokenType() == eToken_start) {
-    nsCOMPtr<nsIAtom> name;
-    rv = NameFromNode(aNode, getter_AddRefs(name));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    // Don't include base tags in output.
-    if (name == nsGkAtoms::base) {
-      return NS_OK;
-    }
-
-    if (!sAllowedTags || !sAllowedTags->GetEntry(name)) {
-      if (!mProcessStyle || name != nsGkAtoms::style) {
-        return NS_OK;
-      }
-    }
-  }
-
-  return nsHTMLFragmentContentSink::AddLeaf(aNode);
-}
-
-NS_IMETHODIMP
-nsHTMLParanoidFragmentSink::AddComment(const nsIParserNode& aNode)
-{
-  if (mProcessComments)
-    return nsHTMLFragmentContentSink::AddComment(aNode);
-  // no comments
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLParanoidFragmentSink::AddProcessingInstruction(const nsIParserNode& aNode)
-{
-  // no PIs
-  return NS_OK;
-}
--- a/content/xml/document/src/nsXMLFragmentContentSink.cpp
+++ b/content/xml/document/src/nsXMLFragmentContentSink.cpp
@@ -474,319 +474,8 @@ nsXMLFragmentContentSink::DidProcessATok
 }
 
 NS_IMETHODIMP
 nsXMLFragmentContentSink::IgnoreFirstContainer()
 {
   NS_NOTREACHED("XML isn't as broken as HTML");
   return NS_ERROR_FAILURE;
 }
-
-
-// nsXHTMLParanoidFragmentSink
-
-// Find the whitelist of allowed elements and attributes in
-// nsContentSink.h We share it with nsHTMLParanoidFragmentSink
-
-class nsXHTMLParanoidFragmentSink : public nsXMLFragmentContentSink
-{
-public:
-  nsXHTMLParanoidFragmentSink(PRBool aAllContent = PR_FALSE);
-
-  static nsresult Init();
-  static void Cleanup();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-  
-  // nsXMLContentSink
-  nsresult AddAttributes(const PRUnichar** aNode, nsIContent* aContent);
-
-  // nsIExpatSink
-  NS_IMETHOD HandleStartElement(const PRUnichar *aName,
-                                const PRUnichar **aAtts,
-                                PRUint32 aAttsCount, PRInt32 aIndex,
-                                PRUint32 aLineNumber);
-    
-  NS_IMETHOD HandleEndElement(const PRUnichar *aName);
-
-  NS_IMETHOD HandleComment(const PRUnichar *aName);
-
-  NS_IMETHOD HandleProcessingInstruction(const PRUnichar *aTarget, 
-                                         const PRUnichar *aData);
-
-  NS_IMETHOD HandleCDataSection(const PRUnichar *aData, 
-                                PRUint32 aLength);
-
-  NS_IMETHOD HandleCharacterData(const PRUnichar *aData,
-                                 PRUint32 aLength);
-protected:
-  PRUint32 mSkipLevel; // used when we descend into <style> or <script>
-
-  nsCOMPtr<nsIPrincipal> mNullPrincipal;
-
-  // Use nsTHashTable as a hash set for our whitelists
-  static nsTHashtable<nsISupportsHashKey>* sAllowedTags;
-  static nsTHashtable<nsISupportsHashKey>* sAllowedAttributes;
-};
-
-nsTHashtable<nsISupportsHashKey>* nsXHTMLParanoidFragmentSink::sAllowedTags;
-nsTHashtable<nsISupportsHashKey>* nsXHTMLParanoidFragmentSink::sAllowedAttributes;
-
-nsXHTMLParanoidFragmentSink::nsXHTMLParanoidFragmentSink(PRBool aAllContent):
-  nsXMLFragmentContentSink(aAllContent), mSkipLevel(0)
-{
-}
-
-nsresult
-nsXHTMLParanoidFragmentSink::Init()
-{
-  nsresult rv = NS_ERROR_FAILURE;
-  
-  if (sAllowedTags) {
-    return NS_OK;
-  }
-
-  sAllowedTags = new nsTHashtable<nsISupportsHashKey>();
-  if (sAllowedTags) {
-    rv = sAllowedTags->Init(80);
-    for (PRUint32 i = 0; kDefaultAllowedTags[i] && NS_SUCCEEDED(rv); i++) {
-      if (!sAllowedTags->PutEntry(*kDefaultAllowedTags[i])) {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-  }
-
-  sAllowedAttributes = new nsTHashtable<nsISupportsHashKey>();
-  if (sAllowedAttributes && NS_SUCCEEDED(rv)) {
-    rv = sAllowedAttributes->Init(80);
-    for (PRUint32 i = 0;
-         kDefaultAllowedAttributes[i] && NS_SUCCEEDED(rv); i++) {
-      if (!sAllowedAttributes->PutEntry(*kDefaultAllowedAttributes[i])) {
-        rv = NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-  }
-
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to populate whitelist hash sets");
-    Cleanup();
-  }
-
-  return rv;
-}
-
-void
-nsXHTMLParanoidFragmentSink::Cleanup()
-{
-  if (sAllowedTags) {
-    delete sAllowedTags;
-    sAllowedTags = nsnull;
-  }
-  
-  if (sAllowedAttributes) {
-    delete sAllowedAttributes;
-    sAllowedAttributes = nsnull;
-  }
-}
-
-nsresult
-NS_NewXHTMLParanoidFragmentSink(nsIFragmentContentSink** aResult)
-{
-  nsresult rv = nsXHTMLParanoidFragmentSink::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsXHTMLParanoidFragmentSink* it = new nsXHTMLParanoidFragmentSink();
-  NS_ADDREF(*aResult = it);
-  
-  return NS_OK;
-}
-
-nsresult
-NS_NewXHTMLParanoidFragmentSink2(nsIFragmentContentSink** aResult)
-{
-  nsXHTMLParanoidFragmentSink* it = new nsXHTMLParanoidFragmentSink(PR_TRUE);
-  if (!it) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
-  nsresult rv = nsXHTMLParanoidFragmentSink::Init();
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ADDREF(*aResult = it);
-  
-  return NS_OK;
-}
-
-void
-NS_XHTMLParanoidFragmentSinkShutdown()
-{
-  nsXHTMLParanoidFragmentSink::Cleanup();
-}
-
-NS_IMPL_ISUPPORTS_INHERITED0(nsXHTMLParanoidFragmentSink,
-                             nsXMLFragmentContentSink)
-
-nsresult
-nsXHTMLParanoidFragmentSink::AddAttributes(const PRUnichar** aAtts,
-                                           nsIContent* aContent)
-{
-  nsresult rv = NS_OK;
-
-  // use this to check for safe URIs in the few attributes that allow them
-  nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
-  nsCOMPtr<nsIURI> baseURI;
-  PRUint32 flags = nsIScriptSecurityManager::DISALLOW_INHERIT_PRINCIPAL;
-
-  // scrub URI attributes that point at dangerous content
-  // We have to do this here, because this is where we have a base URI,
-  // but we can't do all the scrubbing here, because other parts of the
-  // code get the attributes before this method is called.
-  nsTArray<const PRUnichar *> allowedAttrs;
-  PRInt32 nameSpaceID;
-  nsCOMPtr<nsIAtom> prefix, localName;
-
-  if (!mNullPrincipal) {
-      mNullPrincipal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID, &rv);
-      NS_ENSURE_SUCCESS(rv, rv);
-  }
-
-  while (*aAtts) {
-    nsContentUtils::SplitExpatName(aAtts[0], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-    // check the attributes we allow that contain URIs
-    if (IsAttrURI(localName)) {
-      if (!aAtts[1])
-        rv = NS_ERROR_FAILURE;
-      if (!baseURI)
-        baseURI = aContent->GetBaseURI();
-      nsCOMPtr<nsIURI> attrURI;
-      rv = NS_NewURI(getter_AddRefs(attrURI), nsDependentString(aAtts[1]),
-                     nsnull, baseURI);
-      if (NS_SUCCEEDED(rv)) {
-        rv = secMan->CheckLoadURIWithPrincipal(mNullPrincipal, attrURI, flags);
-      }
-    }
-
-    if (NS_SUCCEEDED(rv)) {
-      allowedAttrs.AppendElement(aAtts[0]);
-      allowedAttrs.AppendElement(aAtts[1]);
-    }
-
-    aAtts += 2;
-  }
-  allowedAttrs.AppendElement((const PRUnichar*) nsnull);
-
-  return nsXMLFragmentContentSink::AddAttributes(allowedAttrs.Elements(),
-                                                 aContent);
-}
-
-NS_IMETHODIMP
-nsXHTMLParanoidFragmentSink::HandleStartElement(const PRUnichar *aName,
-                                                const PRUnichar **aAtts,
-                                                PRUint32 aAttsCount,
-                                                PRInt32 aIndex,
-                                                PRUint32 aLineNumber)
-{
-  PRInt32 nameSpaceID;
-  nsCOMPtr<nsIAtom> prefix, localName;
-  nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
-                                 getter_AddRefs(localName), &nameSpaceID);
-  
-  // If the element is not in the XHTML namespace, bounce it
-  if (nameSpaceID != kNameSpaceID_XHTML)
-    return NS_OK;
-  
-  // bounce it if it's not on the whitelist or we're inside
-  // <script> or <style>
-  if (mSkipLevel != 0 ||
-      localName == nsGkAtoms::script ||
-      localName == nsGkAtoms::style) {
-    ++mSkipLevel; // track this so we don't spew script text
-    return NS_OK;
-  }  
-  
-  if (!sAllowedTags || !sAllowedTags->GetEntry(localName))
-    return NS_OK;
-  
-  // It's an allowed element, so let's scrub the attributes
-  nsTArray<const PRUnichar *> allowedAttrs;
-  for (PRUint32 i = 0; i < aAttsCount; i += 2) {
-    nsContentUtils::SplitExpatName(aAtts[i], getter_AddRefs(prefix),
-                                   getter_AddRefs(localName), &nameSpaceID);
-    // Add if it's xmlns, xml: or on the HTML whitelist
-    if (nameSpaceID == kNameSpaceID_XMLNS ||
-        nameSpaceID == kNameSpaceID_XML ||
-        (sAllowedAttributes && sAllowedAttributes->GetEntry(localName))) {
-      allowedAttrs.AppendElement(aAtts[i]);
-      allowedAttrs.AppendElement(aAtts[i + 1]);
-    }
-  }
-  allowedAttrs.AppendElement((const PRUnichar*) nsnull);
-  return
-    nsXMLFragmentContentSink::HandleStartElement(aName,
-                                                 allowedAttrs.Elements(),
-                                                 allowedAttrs.Length() - 1,
-                                                 aIndex,
-                                                 aLineNumber);
-}
-
-NS_IMETHODIMP 
-nsXHTMLParanoidFragmentSink::HandleEndElement(const PRUnichar *aName)
-{
-  PRInt32 nameSpaceID;
-  nsCOMPtr<nsIAtom> prefix, localName;
-  nsContentUtils::SplitExpatName(aName, getter_AddRefs(prefix),
-                                 getter_AddRefs(localName), &nameSpaceID);
-  
-  // If the element is not in the XHTML namespace, bounce it
-  if (nameSpaceID != kNameSpaceID_XHTML) {
-    return NS_OK;
-  }
-  
-  if (mSkipLevel != 0) {
-    --mSkipLevel;
-    return NS_OK;
-  }
-
-  if (!sAllowedTags || !sAllowedTags->GetEntry(localName)) {
-    return NS_OK;
-  }
-
-  return nsXMLFragmentContentSink::HandleEndElement(aName);
-}
-
-NS_IMETHODIMP
-nsXHTMLParanoidFragmentSink::
-HandleProcessingInstruction(const PRUnichar *aTarget, 
-                            const PRUnichar *aData)
-{
-  // We don't do PIs
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXHTMLParanoidFragmentSink::HandleComment(const PRUnichar *aName)
-{
-  // We don't do comments
-  return NS_OK;
-}
-
-// We pass all character data through, unless we're inside <script>
-NS_IMETHODIMP 
-nsXHTMLParanoidFragmentSink::HandleCDataSection(const PRUnichar *aData, 
-                                                PRUint32 aLength)
-{
-  if (mSkipLevel != 0) {
-    return NS_OK;
-  }
-
-  return nsXMLFragmentContentSink::HandleCDataSection(aData, aLength);
-}
-
-NS_IMETHODIMP 
-nsXHTMLParanoidFragmentSink::HandleCharacterData(const PRUnichar *aData, 
-                                                 PRUint32 aLength)
-{
-  if (mSkipLevel != 0) {
-    return NS_OK;
-  }
-
-  return nsXMLFragmentContentSink::HandleCharacterData(aData, aLength);
-}
--- a/editor/libeditor/html/nsHTMLDataTransfer.cpp
+++ b/editor/libeditor/html/nsHTMLDataTransfer.cpp
@@ -79,18 +79,19 @@
 #include "nsIDOMDocumentFragment.h"
 #include "nsIPresShell.h"
 #include "nsPresContext.h"
 #include "nsIParser.h"
 #include "nsParserCIID.h"
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsLinebreakConverter.h"
-#include "nsIFragmentContentSink.h"
-#include "nsIContentSink.h"
+#include "nsAHtml5FragmentParser.h"
+#include "nsHtml5Module.h"
+#include "nsTreeSanitizer.h"
 
 // netwerk
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsIMIMEService.h"
 
 // Drag & Drop, Clipboard
 #include "nsIClipboard.h"
@@ -2584,43 +2585,53 @@ nsresult nsHTMLEditor::CreateDOMFragment
 
   nsCOMPtr<nsIDOMDocument> domDoc;
   GetDocument(getter_AddRefs(domDoc));
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   
   // if we have context info, create a fragment for that
-  nsAutoTArray<nsString, 32> tagStack;
   nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
   nsCOMPtr<nsIDOMNode> contextLeaf, junk;
   if (!aContextStr.IsEmpty())
   {
-    res = ParseFragment(aContextStr, tagStack, doc, address_of(contextAsNode),
+    res = ParseFragment(aContextStr, nsnull, doc, address_of(contextAsNode),
                         aTrustedInput);
     NS_ENSURE_SUCCESS(res, res);
     NS_ENSURE_TRUE(contextAsNode, NS_ERROR_FAILURE);
 
     res = StripFormattingNodes(contextAsNode);
     NS_ENSURE_SUCCESS(res, res);
 
     RemoveBodyAndHead(contextAsNode);
 
     res = FindTargetNode(contextAsNode, contextLeaf);
     if (res == NS_FOUND_TARGET)
       res = NS_OK;
     NS_ENSURE_SUCCESS(res, res);
   }
 
-  // get the tagstack for the context
-  res = CreateTagStack(tagStack, contextLeaf);
-  NS_ENSURE_SUCCESS(res, res);
+  nsCOMPtr<nsIContent> contextLeafAsContent = do_QueryInterface(contextLeaf);
 
   // create fragment for pasted html
-  res = ParseFragment(aInputString, tagStack, doc, outFragNode, aTrustedInput);
+  nsIAtom* contextAtom;
+  if (contextLeafAsContent) {
+    contextAtom = contextLeafAsContent->Tag();
+    if (contextAtom == nsGkAtoms::html) {
+      contextAtom = nsGkAtoms::body;
+    }
+  } else {
+    contextAtom = nsGkAtoms::body;
+  }
+  res = ParseFragment(aInputString,
+                      contextAtom,
+                      doc,
+                      outFragNode,
+                      aTrustedInput);
   NS_ENSURE_SUCCESS(res, res);
   NS_ENSURE_TRUE(*outFragNode, NS_ERROR_FAILURE);
 
   RemoveBodyAndHead(*outFragNode);
 
   if (contextAsNode)
   {
     // unite the two trees
@@ -2668,110 +2679,47 @@ nsresult nsHTMLEditor::CreateDOMFragment
   }
 
   GetLengthOfDOMNode(*outEndNode, (PRUint32&)*outEndOffset);
   return res;
 }
 
 
 nsresult nsHTMLEditor::ParseFragment(const nsAString & aFragStr,
-                                     nsTArray<nsString> &aTagStack,
+                                     nsIAtom* aContextLocalName,
                                      nsIDocument* aTargetDocument,
                                      nsCOMPtr<nsIDOMNode> *outNode,
                                      PRBool aTrustedInput)
 {
-  // figure out if we are parsing full context or not
-  PRBool bContext = aTagStack.IsEmpty();
-
-  // create the parser to do the conversion.
-  nsresult res;
-  nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &res);
-  NS_ENSURE_SUCCESS(res, res);
-  NS_ENSURE_TRUE(parser, NS_ERROR_FAILURE);
-
-  // create the html fragment sink
-  nsCOMPtr<nsIContentSink> sink;
-  if (aTrustedInput) {
-    if (bContext)
-      sink = do_CreateInstance(NS_HTMLFRAGMENTSINK2_CONTRACTID);
-    else
-      sink = do_CreateInstance(NS_HTMLFRAGMENTSINK_CONTRACTID);
-  } else {
-    if (bContext)
-      sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK2_CONTRACTID);
-    else
-      sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID);
-
-    nsCOMPtr<nsIParanoidFragmentContentSink> paranoidSink(do_QueryInterface(sink));
-    NS_ASSERTION(paranoidSink, "Our content sink is paranoid");
-    if (bContext) {
-      // Allow comments for the context to catch our placeholder cookie
-      paranoidSink->AllowComments();
-    } else {
-      // Allow style elements and attributes for the actual content
-      paranoidSink->AllowStyles();
-    }
+  // The old code created a new parser every time. This is inefficient.
+  // However, the target document is not required to be an HTML document,
+  // So avoid using the cached parser of aDocument. Once bug 596182 is fixed,
+  // use the global parser here.
+  nsCOMPtr<nsIParser> parser = nsHtml5Module::NewHtml5Parser();
+  nsAHtml5FragmentParser* asFragmentParser =
+      static_cast<nsAHtml5FragmentParser*> (parser.get());
+  nsCOMPtr<nsIDOMDocumentFragment> frag;
+  NS_NewDocumentFragment(getter_AddRefs(frag),
+                         aTargetDocument->NodeInfoManager());
+  nsCOMPtr<nsIContent> fragment = do_QueryInterface(frag);
+  asFragmentParser->ParseHtml5Fragment(aFragStr,
+                                      fragment,
+                                      aContextLocalName ?
+                                          aContextLocalName : nsGkAtoms::body,
+                                      kNameSpaceID_XHTML,
+                                      PR_FALSE,
+                                      PR_TRUE);
+  if (!aTrustedInput) {
+    nsTreeSanitizer sanitizer(!!aContextLocalName, !aContextLocalName);
+    sanitizer.Sanitize(fragment);
   }
-
-  NS_ENSURE_TRUE(sink, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIFragmentContentSink> fragSink(do_QueryInterface(sink));
-  NS_ENSURE_TRUE(fragSink, NS_ERROR_FAILURE);
-
-  fragSink->SetTargetDocument(aTargetDocument);
-
-  // parse the fragment
-  parser->SetContentSink(sink);
-  if (bContext)
-    parser->Parse(aFragStr, (void*)0, NS_LITERAL_CSTRING("text/html"), PR_TRUE, eDTDMode_fragment);
-  else
-    parser->ParseFragment(aFragStr, 0, aTagStack, PR_FALSE, NS_LITERAL_CSTRING("text/html"), eDTDMode_quirks);
-  // get the fragment node
-  nsCOMPtr<nsIDOMDocumentFragment> contextfrag;
-  res = fragSink->GetFragment(PR_TRUE, getter_AddRefs(contextfrag));
-  NS_ENSURE_SUCCESS(res, res);
-  *outNode = do_QueryInterface(contextfrag);
-  
-  return res;
+  *outNode = do_QueryInterface(frag);
+  return NS_OK;
 }
 
-nsresult nsHTMLEditor::CreateTagStack(nsTArray<nsString> &aTagStack, nsIDOMNode *aNode)
-{
-  nsresult res = NS_OK;
-  nsCOMPtr<nsIDOMNode> node= aNode;
-  PRBool bSeenBody = PR_FALSE;
-  
-  while (node) 
-  {
-    if (nsTextEditUtils::IsBody(node))
-      bSeenBody = PR_TRUE;
-    nsCOMPtr<nsIDOMNode> temp = node;
-    PRUint16 nodeType;
-    
-    node->GetNodeType(&nodeType);
-    if (nsIDOMNode::ELEMENT_NODE == nodeType)
-    {
-      nsString* tagName = aTagStack.AppendElement();
-      NS_ENSURE_TRUE(tagName, NS_ERROR_OUT_OF_MEMORY);
-
-      node->GetNodeName(*tagName);
-      // printf("%s\n",NS_LossyConvertUTF16toASCII(tagName).get());
-    }
-
-    res = temp->GetParentNode(getter_AddRefs(node));
-    NS_ENSURE_SUCCESS(res, res);  
-  }
-  
-  if (!bSeenBody)
-  {
-      aTagStack.AppendElement(NS_LITERAL_STRING("BODY"));
-  }
-  return res;
-}
-
-
 nsresult nsHTMLEditor::CreateListOfNodesToPaste(nsIDOMNode  *aFragmentAsNode,
                                                 nsCOMArray<nsIDOMNode>& outNodeList,
                                                 nsIDOMNode *aStartNode,
                                                 PRInt32 aStartOffset,
                                                 nsIDOMNode *aEndNode,
                                                 PRInt32 aEndOffset)
 {
   NS_ENSURE_TRUE(aFragmentAsNode, NS_ERROR_NULL_POINTER);
--- a/editor/libeditor/html/nsHTMLEditor.h
+++ b/editor/libeditor/html/nsHTMLEditor.h
@@ -623,17 +623,17 @@ protected:
                                         const nsAString & aContextStr,
                                         const nsAString & aInfoStr,
                                         nsCOMPtr<nsIDOMNode> *outFragNode,
                                         nsCOMPtr<nsIDOMNode> *outStartNode,
                                         nsCOMPtr<nsIDOMNode> *outEndNode,
                                         PRInt32 *outStartOffset,
                                         PRInt32 *outEndOffset,
                                         PRBool aTrustedInput);
-  nsresult   ParseFragment(const nsAString & aStr, nsTArray<nsString> &aTagStack,
+  nsresult   ParseFragment(const nsAString & aStr, nsIAtom* aContextLocalName,
                            nsIDocument* aTargetDoc,
                            nsCOMPtr<nsIDOMNode> *outNode,
                            PRBool aTrustedInput);
   nsresult   CreateListOfNodesToPaste(nsIDOMNode  *aFragmentAsNode,
                                       nsCOMArray<nsIDOMNode>& outNodeList,
                                       nsIDOMNode *aStartNode,
                                       PRInt32 aStartOffset,
                                       nsIDOMNode *aEndNode,
--- a/editor/libeditor/html/tests/test_bug520189.html
+++ b/editor/libeditor/html/tests/test_bug520189.html
@@ -57,16 +57,30 @@ https://bugzilla.mozilla.org/show_bug.cg
   <iframe id="oo" src="about:blank"></iframe>
   <div id="pp" contenteditable="true"></div>
   <iframe id="qq" src="about:blank"></iframe>
   <div id="rr" contenteditable="true"></div>
   <iframe id="ss" src="about:blank"></iframe>
   <div id="tt" contenteditable="true"></div>
   <iframe id="uu" src="about:blank"></iframe>
   <div id="vv" contenteditable="true"></div>
+  <div id="sss" contenteditable="true"></div>
+  <iframe id="ssss" src="about:blank"></iframe>
+  <div id="ttt" contenteditable="true"></div>
+  <iframe id="tttt" src="about:blank"></iframe>
+  <div id="uuu" contenteditable="true"></div>
+  <iframe id="uuuu" src="about:blank"></iframe>
+  <div id="vvv" contenteditable="true"></div>
+  <iframe id="vvvv" src="about:blank"></iframe>
+  <div id="www" contenteditable="true"></div>
+  <iframe id="wwww" src="about:blank"></iframe>
+  <div id="xxx" contenteditable="true"></div>
+  <iframe id="xxxx" src="about:blank"></iframe>
+  <div id="yyy" contenteditable="true"></div>
+  <iframe id="yyyy" src="about:blank"></iframe>
 </div>
 <pre id="test">
 <script type="application/javascript">
 
 /** Test for Bug 520182 **/
 
 const dataPayload = "foo<iframe src=\"data:text/html,bar\"></iframe>baz";
 const jsPayload = "foo<iframe src=\"javascript:void('bar');\"></iframe>baz";
@@ -87,16 +101,23 @@ const invalidStyle7Payload = "<html><hea
 const invalidStyle8Payload = "foo<style>@-moz-document url(http://example.com/) {};</style>baz";
 const invalidStyle9Payload = "foo<style>@-moz-keyframes bar {};</style>baz";
 const nestedStylePayload = "foo<style>#bar1{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-1&quot;/>');<style></style>#bar2{-moz-binding:url('data:text/xml,<?xml version=&quot;1.0&quot;><binding xmlns=&quot;http://www.mozilla.org/xbl&quot; id=&quot;binding-2&quot;/>');</style>baz";
 const validImgSrc1Payload = "foo<img src=\"data:image/png,bar\">baz";
 const validImgSrc2Payload = "foo<img src=\"javascript:void('bar');\">baz";
 const validImgSrc3Payload = "foo<img src=\"file:///bar.png\">baz";
 const validDataFooPayload = "foo<span data-bar=\"value\">baz</span>";
 const validDataFoo2Payload = "foo<span _bar=\"value\">baz</span>";
+const svgPayload = "foo<svg><title>svgtitle</title></svg>bar";
+const svg2Payload = "foo<svg><bogussvg/></svg>bar";
+const mathPayload = "foo<math><bogusmath/></math>bar";
+const math2Payload = "foo<math><style>@import \"yyy.css\";</style</math>bar";
+const math3Payload = "foo<math><mi></mi></math>bar";
+const videoPayload = "foo<video></video>bar";
+const microdataPayload = "<head><meta name=foo content=bar><link rel=stylesheet href=url></head><body><meta itemprop=foo content=bar><link itemprop=bar href=url></body>";
 
 var tests = [
   {
     id: "a",
     isIFrame: true,
     payload: dataPayload,
     iframeCount: 0,
     rootElement: function() document.getElementById("a").contentDocument.documentElement
@@ -416,16 +437,107 @@ var tests = [
     rootElement: function() document.getElementById("uu").contentDocument.documentElement,
     checkResult: function(html) is(html.indexOf("@-moz-keyframes"), -1, "Should not have retained the @-moz-keyframes rule")
   },
   {
     id: "vv",
     payload: invalidStyle9Payload,
     rootElement: function() document.getElementById("vv"),
     checkResult: function(html) is(html.indexOf("@-moz-keyframes"), -1, "Should not have retained the @-moz-keyframes rule")
+  },
+  {
+    id: "sss",
+    payload: svgPayload,
+    rootElement: function() document.getElementById("sss"),
+    checkResult: function(html) isnot(html.indexOf("svgtitle"), -1, "Should have retained SVG title")
+  },
+  {
+    id: "ssss",
+    isIFrame: true,
+    payload: svgPayload,
+    rootElement: function() document.getElementById("ssss").contentDocument.documentElement,
+    checkResult: function(html) isnot(html.indexOf("svgtitle"), -1, "Should have retained SVG title")
+  },
+  {
+    id: "ttt",
+    payload: svg2Payload,
+    rootElement: function() document.getElementById("ttt"),
+    checkResult: function(html) is(html.indexOf("bogussvg"), -1, "Should have dropped bogussvg element")
+  },
+  {
+    id: "tttt",
+    isIFrame: true,
+    payload: svg2Payload,
+    rootElement: function() document.getElementById("tttt").contentDocument.documentElement,
+    checkResult: function(html) is(html.indexOf("bogussvg"), -1, "Should have dropped bogussvg element")
+  },
+  {
+    id: "uuu",
+    payload: mathPayload,
+    rootElement: function() document.getElementById("uuu"),
+    checkResult: function(html) is(html.indexOf("bogusmath"), -1, "Should have dropped bogusmath element")
+  },
+  {
+    id: "uuuu",
+    isIFrame: true,
+    payload: mathPayload,
+    rootElement: function() document.getElementById("uuuu").contentDocument.documentElement,
+    checkResult: function(html) is(html.indexOf("bogusmath"), -1, "Should have dropped bogusmath element")
+  },
+  {
+    id: "vvv",
+    payload: math2Payload,
+    rootElement: function() document.getElementById("vvv"),
+    checkResult: function(html) is(html.indexOf("yyy.css"), -1, "Should have dropped MathML style element")
+  },
+  {
+    id: "vvvv",
+    isIFrame: true,
+    payload: math2Payload,
+    rootElement: function() document.getElementById("vvvv").contentDocument.documentElement,
+    checkResult: function(html) is(html.indexOf("yyy.css"), -1, "Should have dropped MathML style element")
+  },
+  {
+    id: "www",
+    payload: math3Payload,
+    rootElement: function() document.getElementById("www"),
+    checkResult: function(html) isnot(html.indexOf("<mi"), -1, "Should not have dropped MathML mi element")
+  },
+  {
+    id: "wwww",
+    isIFrame: true,
+    payload: math3Payload,
+    rootElement: function() document.getElementById("wwww").contentDocument.documentElement,
+    checkResult: function(html) isnot(html.indexOf("<mi"), -1, "Should not have dropped MathML mi element")
+  },
+  {
+    id: "xxx",
+    payload: videoPayload,
+    rootElement: function() document.getElementById("xxx"),
+    checkResult: function(html) isnot(html.indexOf("controls="), -1, "Should have added the controls attribute")
+  },
+  {
+    id: "xxxx",
+    isIFrame: true,
+    payload: videoPayload,
+    rootElement: function() document.getElementById("xxxx").contentDocument.documentElement,
+    checkResult: function(html) isnot(html.indexOf("controls="), -1, "Should have added the controls attribute")
+  },
+  {
+    id: "yyy",
+    payload: microdataPayload,
+    rootElement: function() document.getElementById("yyy"),
+    checkResult: function(html) { is(html.indexOf("name"), -1, "Should have dropped name."); is(html.indexOf("rel"), -1, "Should have dropped rel."); isnot(html.indexOf("itemprop"), -1, "Should not have dropped itemprop."); }
+  },
+  {
+    id: "yyyy",
+    isIFrame: true,
+    payload: microdataPayload,
+    rootElement: function() document.getElementById("yyyy").contentDocument.documentElement,
+    checkResult: function(html) { is(html.indexOf("name"), -1, "Should have dropped name."); is(html.indexOf("rel"), -1, "Should have dropped rel."); isnot(html.indexOf("itemprop"), -1, "Should not have dropped itemprop."); }
   }
 ];
 
 function doNextTest() {
   if (typeof testCounter == "undefined")
     testCounter = 0;
   else if (++testCounter == tests.length) {
     SimpleTest.finish();
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -526,22 +526,18 @@ MAKE_CTOR(CreateSubtreeIterator,        
 MAKE_CTOR(CreateTextEncoder,              nsIDocumentEncoder,          NS_NewTextEncoder)
 MAKE_CTOR(CreateHTMLCopyTextEncoder,      nsIDocumentEncoder,          NS_NewHTMLCopyTextEncoder)
 MAKE_CTOR(CreateXMLContentSerializer,     nsIContentSerializer,        NS_NewXMLContentSerializer)
 MAKE_CTOR(CreateHTMLContentSerializer,    nsIContentSerializer,        NS_NewHTMLContentSerializer)
 MAKE_CTOR(CreateXHTMLContentSerializer,   nsIContentSerializer,        NS_NewXHTMLContentSerializer)
 MAKE_CTOR(CreatePlainTextSerializer,      nsIContentSerializer,        NS_NewPlainTextSerializer)
 MAKE_CTOR(CreateHTMLFragmentSink,         nsIFragmentContentSink,      NS_NewHTMLFragmentContentSink)
 MAKE_CTOR(CreateHTMLFragmentSink2,        nsIFragmentContentSink,      NS_NewHTMLFragmentContentSink2)
-MAKE_CTOR(CreateHTMLParanoidFragmentSink, nsIFragmentContentSink,      NS_NewHTMLParanoidFragmentSink)
-MAKE_CTOR(CreateHTMLParanoidFragmentSink2,nsIFragmentContentSink,      NS_NewHTMLParanoidFragmentSink2)
 MAKE_CTOR(CreateXMLFragmentSink,          nsIFragmentContentSink,      NS_NewXMLFragmentContentSink)
 MAKE_CTOR(CreateXMLFragmentSink2,         nsIFragmentContentSink,      NS_NewXMLFragmentContentSink2)
-MAKE_CTOR(CreateXHTMLParanoidFragmentSink,nsIFragmentContentSink,      NS_NewXHTMLParanoidFragmentSink)
-MAKE_CTOR(CreateXHTMLParanoidFragmentSink2,nsIFragmentContentSink,     NS_NewXHTMLParanoidFragmentSink2)
 MAKE_CTOR(CreateSanitizingHTMLSerializer, nsIContentSerializer,        NS_NewSanitizingHTMLSerializer)
 MAKE_CTOR(CreateXBLService,               nsIXBLService,               NS_NewXBLService)
 MAKE_CTOR(CreateContentPolicy,            nsIContentPolicy,            NS_NewContentPolicy)
 #ifdef MOZ_XUL
 MAKE_CTOR(CreateXULSortService,           nsIXULSortService,           NS_NewXULSortService)
 // NS_NewXULContentBuilder
 // NS_NewXULTreeBuilder
 MAKE_CTOR(CreateXULDocument,              nsIXULDocument,              NS_NewXULDocument)
@@ -777,23 +773,19 @@ NS_DEFINE_NAMED_CID(NS_CANVASRENDERINGCO
 NS_DEFINE_NAMED_CID(NS_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCOPY_TEXT_ENCODER_CID);
 NS_DEFINE_NAMED_CID(NS_XMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_XHTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLCONTENTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_PLAINTEXTSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLFRAGMENTSINK_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLFRAGMENTSINK2_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLPARANOIDFRAGMENTSINK_CID);
-NS_DEFINE_NAMED_CID(NS_HTMLPARANOIDFRAGMENTSINK2_CID);
 NS_DEFINE_NAMED_CID(MOZ_SANITIZINGHTMLSERIALIZER_CID);
 NS_DEFINE_NAMED_CID(NS_XMLFRAGMENTSINK_CID);
 NS_DEFINE_NAMED_CID(NS_XMLFRAGMENTSINK2_CID);
-NS_DEFINE_NAMED_CID(NS_XHTMLPARANOIDFRAGMENTSINK_CID);
-NS_DEFINE_NAMED_CID(NS_XHTMLPARANOIDFRAGMENTSINK2_CID);
 NS_DEFINE_NAMED_CID(NS_XBLSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_CONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_DATADOCUMENTCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_NODATAPROTOCOLCONTENTPOLICY_CID);
 NS_DEFINE_NAMED_CID(NS_XULCONTROLLERS_CID);
 #ifdef MOZ_XUL
 NS_DEFINE_NAMED_CID(NS_XULSORTSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_XULTEMPLATEBUILDER_CID);
@@ -920,23 +912,19 @@ static const mozilla::Module::CIDEntry k
   { &kNS_TEXT_ENCODER_CID, false, NULL, CreateTextEncoder },
   { &kNS_HTMLCOPY_TEXT_ENCODER_CID, false, NULL, CreateHTMLCopyTextEncoder },
   { &kNS_XMLCONTENTSERIALIZER_CID, false, NULL, CreateXMLContentSerializer },
   { &kNS_HTMLCONTENTSERIALIZER_CID, false, NULL, CreateHTMLContentSerializer },
   { &kNS_XHTMLCONTENTSERIALIZER_CID, false, NULL, CreateXHTMLContentSerializer },
   { &kNS_PLAINTEXTSERIALIZER_CID, false, NULL, CreatePlainTextSerializer },
   { &kNS_HTMLFRAGMENTSINK_CID, false, NULL, CreateHTMLFragmentSink },
   { &kNS_HTMLFRAGMENTSINK2_CID, false, NULL, CreateHTMLFragmentSink2 },
-  { &kNS_HTMLPARANOIDFRAGMENTSINK_CID, false, NULL, CreateHTMLParanoidFragmentSink },
-  { &kNS_HTMLPARANOIDFRAGMENTSINK2_CID, false, NULL, CreateHTMLParanoidFragmentSink2 },
   { &kMOZ_SANITIZINGHTMLSERIALIZER_CID, false, NULL, CreateSanitizingHTMLSerializer },
   { &kNS_XMLFRAGMENTSINK_CID, false, NULL, CreateXMLFragmentSink },
   { &kNS_XMLFRAGMENTSINK2_CID, false, NULL, CreateXMLFragmentSink2 },
-  { &kNS_XHTMLPARANOIDFRAGMENTSINK_CID, false, NULL, CreateXHTMLParanoidFragmentSink },
-  { &kNS_XHTMLPARANOIDFRAGMENTSINK2_CID, false, NULL, CreateXHTMLParanoidFragmentSink2 },
   { &kNS_XBLSERVICE_CID, false, NULL, CreateXBLService },
   { &kNS_CONTENTPOLICY_CID, false, NULL, CreateContentPolicy },
   { &kNS_DATADOCUMENTCONTENTPOLICY_CID, false, NULL, nsDataDocumentContentPolicyConstructor },
   { &kNS_NODATAPROTOCOLCONTENTPOLICY_CID, false, NULL, nsNoDataProtocolContentPolicyConstructor },
   { &kNS_XULCONTROLLERS_CID, false, NULL, NS_NewXULControllers },
 #ifdef MOZ_XUL
   { &kNS_XULSORTSERVICE_CID, false, NULL, CreateXULSortService },
   { &kNS_XULTEMPLATEBUILDER_CID, false, NULL, NS_NewXULContentBuilder },
@@ -1064,23 +1052,19 @@ static const mozilla::Module::ContractID
   { NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "application/xhtml+xml", &kNS_XHTMLCONTENTSERIALIZER_CID },
   { NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "image/svg+xml", &kNS_XMLCONTENTSERIALIZER_CID },
   { NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "text/html", &kNS_HTMLCONTENTSERIALIZER_CID },
   { NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "application/vnd.mozilla.xul+xml", &kNS_XMLCONTENTSERIALIZER_CID },
   { NS_CONTENTSERIALIZER_CONTRACTID_PREFIX "text/plain", &kNS_PLAINTEXTSERIALIZER_CID },
   { NS_PLAINTEXTSINK_CONTRACTID, &kNS_PLAINTEXTSERIALIZER_CID },
   { NS_HTMLFRAGMENTSINK_CONTRACTID, &kNS_HTMLFRAGMENTSINK_CID },
   { NS_HTMLFRAGMENTSINK2_CONTRACTID, &kNS_HTMLFRAGMENTSINK2_CID },
-  { NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID, &kNS_HTMLPARANOIDFRAGMENTSINK_CID },
-  { NS_HTMLPARANOIDFRAGMENTSINK2_CONTRACTID, &kNS_HTMLPARANOIDFRAGMENTSINK2_CID },
   { MOZ_SANITIZINGHTMLSERIALIZER_CONTRACTID, &kMOZ_SANITIZINGHTMLSERIALIZER_CID },
   { NS_XMLFRAGMENTSINK_CONTRACTID, &kNS_XMLFRAGMENTSINK_CID },
   { NS_XMLFRAGMENTSINK2_CONTRACTID, &kNS_XMLFRAGMENTSINK2_CID },
-  { NS_XHTMLPARANOIDFRAGMENTSINK_CONTRACTID, &kNS_XHTMLPARANOIDFRAGMENTSINK_CID },
-  { NS_XHTMLPARANOIDFRAGMENTSINK2_CONTRACTID, &kNS_XHTMLPARANOIDFRAGMENTSINK2_CID },
   { "@mozilla.org/xbl;1", &kNS_XBLSERVICE_CID },
   { NS_CONTENTPOLICY_CONTRACTID, &kNS_CONTENTPOLICY_CID },
   { NS_DATADOCUMENTCONTENTPOLICY_CONTRACTID, &kNS_DATADOCUMENTCONTENTPOLICY_CID },
   { NS_NODATAPROTOCOLCONTENTPOLICY_CONTRACTID, &kNS_NODATAPROTOCOLCONTENTPOLICY_CID },
   { "@mozilla.org/xul/xul-controllers;1", &kNS_XULCONTROLLERS_CID },
 #ifdef MOZ_XUL
   { "@mozilla.org/xul/xul-sort-service;1", &kNS_XULSORTSERVICE_CID },
   { "@mozilla.org/xul/xul-template-builder;1", &kNS_XULTEMPLATEBUILDER_CID },
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -68,16 +68,17 @@
 #include "nsFloatManager.h"
 #include "nsSprocketLayout.h"
 #include "nsStackLayout.h"
 #include "nsStyleSet.h"
 #include "nsTextControlFrame.h"
 #include "nsXBLWindowKeyHandler.h"
 #include "txMozillaXSLTProcessor.h"
 #include "nsDOMStorage.h"
+#include "nsTreeSanitizer.h"
 #include "nsCellMap.h"
 #include "nsTextFrameTextRunCache.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsTextFragment.h"
 #include "nsCSSRuleProcessor.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsHTMLDNSPrefetch.h"
 #include "nsHtml5Module.h"
@@ -342,16 +343,18 @@ nsLayoutStatics::Shutdown()
 #ifdef MOZ_SYDNEYAUDIO
   nsAudioStream::ShutdownLibrary();
 #endif
 
   nsCORSListenerProxy::Shutdown();
   
   nsIPresShell::ReleaseStatics();
 
+  nsTreeSanitizer::ReleaseStatics();
+
   nsHtml5Module::ReleaseStatics();
 
   nsRegion::ShutdownStatic();
 
   NS_ShutdownChainItemPool();
 
   nsFrameList::Shutdown();
 
--- a/layout/generic/nsHTMLParts.h
+++ b/layout/generic/nsHTMLParts.h
@@ -230,17 +230,9 @@ NS_NewHTMLContentSink(nsIHTMLContentSink
                       nsIDocument* aDoc, nsIURI* aURL,
                       nsISupports* aContainer, // e.g. docshell
                       nsIChannel* aChannel);
 nsresult
 NS_NewHTMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
 nsresult
 NS_NewHTMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
 
-// This strips all but a whitelist of elements and attributes defined
-// in nsContentSink.h
-nsresult
-NS_NewHTMLParanoidFragmentSink(nsIFragmentContentSink** aInstancePtrResult);
-nsresult
-NS_NewHTMLParanoidFragmentSink2(nsIFragmentContentSink** aInstancePtrResult);
-void
-NS_HTMLParanoidFragmentSinkShutdown();
 #endif /* nsHTMLParts_h___ */
--- a/parser/htmlparser/public/nsIFragmentContentSink.h
+++ b/parser/htmlparser/public/nsIFragmentContentSink.h
@@ -41,20 +41,16 @@
 
 class nsIDOMDocumentFragment;
 class nsIDocument;
 
 #define NS_I_FRAGMENT_CONTENT_SINK_IID \
   { 0x1ecdb30d, 0x1f10, 0x45d2, \
     { 0xa4, 0xf4, 0xec, 0xbc, 0x03, 0x52, 0x9a, 0x7e } }
 
-#define NS_I_PARANOID_FRAGMENT_CONTENT_SINK_IID \
-  { 0x86b5390d, 0xd80e, 0x4a86, \
-    { 0x83, 0xec, 0xda, 0x44, 0xac, 0x5b, 0x8c, 0x5f } }
-
 /**
  * The fragment sink allows a client to parse a fragment of sink, possibly
  * surrounded in context. Also see nsIParser::ParseFragment().
  * Note: once you've parsed a fragment, the fragment sink must be re-set on
  * the parser in order to parse another fragment.
  */
 class nsIFragmentContentSink : public nsISupports {
 public:
@@ -119,47 +115,27 @@ public:
   virtual void AllowStyles() = 0;
 
   /**
    * Allow the content sink to accept comments.
    */
   virtual void AllowComments() = 0;
 };
 
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIParanoidFragmentContentSink,
-                              NS_I_PARANOID_FRAGMENT_CONTENT_SINK_IID)
-
 /**
  * Base version takes string nested in context, content surrounded by
  * WillBuildContent()/DidBuildContent() calls. The 2nd version just loads
  * the whole string.
  */
 
 #define NS_HTMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;1"
 #define NS_HTMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/htmlfragmentsink;2"
-#define NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID \
-"@mozilla.org/htmlparanoidfragmentsink;1"
-#define NS_HTMLPARANOIDFRAGMENTSINK2_CONTRACTID \
-"@mozilla.org/htmlparanoidfragmentsink;2"
 
 #define NS_XMLFRAGMENTSINK_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;1"
 #define NS_XMLFRAGMENTSINK2_CONTRACTID "@mozilla.org/layout/xmlfragmentsink;2"
-#define NS_XHTMLPARANOIDFRAGMENTSINK_CONTRACTID \
-"@mozilla.org/xhtmlparanoidfragmentsink;1"
-#define NS_XHTMLPARANOIDFRAGMENTSINK2_CONTRACTID \
-"@mozilla.org/xhtmlparanoidfragmentsink;2"
-
 
 // the HTML versions are in nsHTMLParts.h
 nsresult
 NS_NewXMLFragmentContentSink(nsIFragmentContentSink** aInstancePtrResult);
 nsresult
 NS_NewXMLFragmentContentSink2(nsIFragmentContentSink** aInstancePtrResult);
 
-// This strips all but a whitelist of elements and attributes defined
-// in nsContentSink.h
-nsresult
-NS_NewXHTMLParanoidFragmentSink(nsIFragmentContentSink** aInstancePtrResult);
-nsresult
-NS_NewXHTMLParanoidFragmentSink2(nsIFragmentContentSink** aInstancePtrResult);
-void
-NS_XHTMLParanoidFragmentSinkShutdown();
 #endif
--- a/toolkit/components/feeds/nsScriptableUnescapeHTML.cpp
+++ b/toolkit/components/feeds/nsScriptableUnescapeHTML.cpp
@@ -60,20 +60,21 @@
 #include "nsIDocument.h"
 #include "nsIContent.h"
 #include "nsAttrName.h"
 #include "nsHTMLParts.h"
 #include "nsContentCID.h"
 #include "nsIScriptableUnescapeHTML.h"
 #include "nsScriptableUnescapeHTML.h"
 #include "nsAutoPtr.h"
+#include "nsTreeSanitizer.h"
+#include "nsAHtml5FragmentParser.h"
+#include "nsHtml5Module.h"
 
 #define XHTML_DIV_TAG "div xmlns=\"http://www.w3.org/1999/xhtml\""
-#define HTML_BODY_TAG "BODY"
-#define HTML_BASE_TAG "BASE"
 
 NS_IMPL_ISUPPORTS1(nsScriptableUnescapeHTML, nsIScriptableUnescapeHTML)
 
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 // From /widget/HTMLConverter
 //
 // Takes HTML and converts it to plain text but in unicode.
@@ -160,53 +161,71 @@ nsScriptableUnescapeHTML::ParseFragment(
       if (escapedSpec)
         base += escapedSpec;
       NS_Free(escapedSpec);
       base.Append(NS_LITERAL_CSTRING("\""));
       tagStack.AppendElement(NS_ConvertUTF8toUTF16(base));
     }  else {
       tagStack.AppendElement(NS_LITERAL_STRING(XHTML_DIV_TAG));
     }
-  } else {
-    // HTML
-    tagStack.AppendElement(NS_LITERAL_STRING(HTML_BODY_TAG));
-    if (aBaseURI) {
-      base.Append(NS_LITERAL_CSTRING((HTML_BASE_TAG)));
-      base.Append(NS_LITERAL_CSTRING(" href=\""));
-      aBaseURI->GetSpec(spec);
-      base = base + spec;
-      base.Append(NS_LITERAL_CSTRING("\""));
-      tagStack.AppendElement(NS_ConvertUTF8toUTF16(base));
-    }
   }
 
   if (NS_SUCCEEDED(rv)) {
-    nsCAutoString contentType;
-    nsDTDMode mode;
-    nsCOMPtr<nsIFragmentContentSink> sink;
+    nsCOMPtr<nsIContent> fragment;
     if (aIsXML) {
-      mode = eDTDMode_full_standards;
+      nsCAutoString contentType;
+      nsCOMPtr<nsIFragmentContentSink> sink;
       contentType = NS_LITERAL_CSTRING("application/xhtml+xml");
-      sink = do_CreateInstance(NS_XHTMLPARANOIDFRAGMENTSINK_CONTRACTID);
+      sink = do_CreateInstance(NS_XMLFRAGMENTSINK_CONTRACTID);
+      if (sink) {
+        sink->SetTargetDocument(document);
+        nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
+        parser->SetContentSink(contentsink);
+        rv = parser->ParseFragment(aFragment, nsnull, tagStack,
+                                   aIsXML, contentType,
+                                   eDTDMode_full_standards);
+        if (NS_SUCCEEDED(rv)) {
+          rv = sink->GetFragment(PR_TRUE, aReturn);
+          fragment = do_QueryInterface(*aReturn);
+        }
+      } else {
+        rv = NS_ERROR_FAILURE;
+      }
     } else {
-      mode = eDTDMode_fragment;
-      contentType = NS_LITERAL_CSTRING("text/html");
-      sink = do_CreateInstance(NS_HTMLPARANOIDFRAGMENTSINK_CONTRACTID);
+      nsCOMPtr<nsIParser> parser = nsHtml5Module::NewHtml5Parser();
+      nsAHtml5FragmentParser* asFragmentParser =
+          static_cast<nsAHtml5FragmentParser*> (parser.get());
+      NS_NewDocumentFragment(aReturn,
+                             document->NodeInfoManager());
+      fragment = do_QueryInterface(*aReturn);
+      asFragmentParser->ParseHtml5Fragment(aFragment,
+                                          fragment,
+                                          nsGkAtoms::body,
+                                          kNameSpaceID_XHTML,
+                                          PR_FALSE,
+                                          PR_TRUE);
+      // Now, set the base URI on all subtree roots.
+      aBaseURI->GetSpec(spec);
+      nsAutoString spec16;
+      CopyUTF8toUTF16(spec, spec16);
+      nsIContent* node = fragment->GetFirstChild();
+      while (node) {
+        if (node->IsElement()) {
+          node->SetAttr(kNameSpaceID_XML,
+                        nsGkAtoms::base,
+                        nsGkAtoms::xml,
+                        spec16,
+                        PR_FALSE);
+        }
+        node = node->GetNextSibling();
+      }
     }
-    if (sink) {
-      sink->SetTargetDocument(document);
-      nsCOMPtr<nsIContentSink> contentsink(do_QueryInterface(sink));
-      parser->SetContentSink(contentsink);
-      rv = parser->ParseFragment(aFragment, nsnull, tagStack,
-                                 aIsXML, contentType, mode);
-      if (NS_SUCCEEDED(rv))
-        rv = sink->GetFragment(PR_TRUE, aReturn);
-
-    } else {
-      rv = NS_ERROR_FAILURE;
+    if (fragment) {
+      nsTreeSanitizer sanitizer(PR_FALSE, PR_FALSE);
+      sanitizer.Sanitize(fragment);
     }
   }
 
   if (scripts_enabled)
       loader->SetEnabled(PR_TRUE);
   
   return rv;
 }