nsParserUtils.cpp (4309B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "nsParserUtils.h" 7 #include "mozilla/NullPrincipal.h" 8 #include "mozilla/dom/DocumentFragment.h" 9 #include "mozilla/dom/Element.h" 10 #include "mozilla/dom/ScriptLoader.h" 11 #include "nsAttrName.h" 12 #include "nsCOMPtr.h" 13 #include "nsContentUtils.h" 14 #include "nsEscape.h" 15 #include "nsHTMLParts.h" 16 #include "nsHtml5Module.h" 17 #include "nsIContent.h" 18 #include "nsIContentSink.h" 19 #include "mozilla/dom/Document.h" 20 #include "nsIDocumentEncoder.h" 21 #include "nsIFragmentContentSink.h" 22 #include "nsIParser.h" 23 #include "nsNetCID.h" 24 #include "nsNetUtil.h" 25 #include "nsString.h" 26 #include "nsTreeSanitizer.h" 27 #include "nsXPCOM.h" 28 29 #define XHTML_DIV_TAG u"div xmlns=\"http://www.w3.org/1999/xhtml\"" 30 31 using namespace mozilla::dom; 32 33 NS_IMPL_ISUPPORTS(nsParserUtils, nsIParserUtils) 34 35 NS_IMETHODIMP 36 nsParserUtils::ConvertToPlainText(const nsAString& aFromStr, uint32_t aFlags, 37 uint32_t aWrapCol, nsAString& aToStr) { 38 return nsContentUtils::ConvertToPlainText(aFromStr, aToStr, aFlags, aWrapCol); 39 } 40 41 template <typename Callable> 42 static nsresult SanitizeWith(const nsAString& aInput, nsAString& aOutput, 43 Callable aDoSanitize) { 44 RefPtr<Document> document = nsContentUtils::CreateInertHTMLDocument(nullptr); 45 if (!document) { 46 return NS_ERROR_FAILURE; 47 } 48 49 nsresult rv = nsContentUtils::ParseDocumentHTML(aInput, document, false); 50 NS_ENSURE_SUCCESS(rv, rv); 51 52 aDoSanitize(document.get()); 53 54 nsCOMPtr<nsIDocumentEncoder> encoder = do_createDocumentEncoder("text/html"); 55 encoder->Init(document, u"text/html"_ns, 56 nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration | 57 nsIDocumentEncoder::OutputNoScriptContent | 58 nsIDocumentEncoder::OutputEncodeBasicEntities | 59 nsIDocumentEncoder::OutputLFLineBreak | 60 nsIDocumentEncoder::OutputRaw); 61 return encoder->EncodeToString(aOutput); 62 } 63 64 NS_IMETHODIMP 65 nsParserUtils::Sanitize(const nsAString& aFromStr, uint32_t aFlags, 66 nsAString& aToStr) { 67 return SanitizeWith(aFromStr, aToStr, [&](Document* aDocument) { 68 nsTreeSanitizer sanitizer(aFlags); 69 sanitizer.Sanitize(aDocument); 70 }); 71 } 72 73 NS_IMETHODIMP 74 nsParserUtils::RemoveConditionalCSS(const nsAString& aFromStr, 75 nsAString& aToStr) { 76 return SanitizeWith(aFromStr, aToStr, [](Document* aDocument) { 77 nsTreeSanitizer::RemoveConditionalCSSFromSubtree(aDocument); 78 }); 79 } 80 81 NS_IMETHODIMP 82 nsParserUtils::ParseFragment(const nsAString& aFragment, uint32_t aFlags, 83 bool aIsXML, nsIURI* aBaseURI, 84 Element* aContextElement, 85 DocumentFragment** aReturn) { 86 NS_ENSURE_ARG(aContextElement); 87 *aReturn = nullptr; 88 89 RefPtr<Document> document = aContextElement->OwnerDoc(); 90 91 nsAutoScriptBlockerSuppressNodeRemoved autoBlocker; 92 93 bool scripts_enabled = false; 94 // stop scripts 95 RefPtr<ScriptLoader> loader = document->GetScriptLoader(); 96 if (loader) { 97 scripts_enabled = loader->GetEnabled(); 98 if (scripts_enabled) { 99 loader->SetEnabled(false); 100 } 101 } 102 103 // Wrap things in a div or body for parsing, but it won't show up in 104 // the fragment. 105 nsresult rv = NS_OK; 106 AutoTArray<nsString, 2> tagStack; 107 RefPtr<DocumentFragment> fragment; 108 if (aIsXML) { 109 // XHTML 110 tagStack.AppendElement(nsLiteralString(XHTML_DIV_TAG)); 111 rv = nsContentUtils::ParseFragmentXML(aFragment, document, tagStack, true, 112 aFlags, getter_AddRefs(fragment)); 113 } else { 114 fragment = new (document->NodeInfoManager()) 115 DocumentFragment(document->NodeInfoManager()); 116 rv = nsContentUtils::ParseFragmentHTML(aFragment, fragment, nsGkAtoms::body, 117 kNameSpaceID_XHTML, false, true, 118 aFlags); 119 } 120 121 if (scripts_enabled) { 122 loader->SetEnabled(true); 123 } 124 125 fragment.forget(aReturn); 126 return rv; 127 }