nsDOMSerializer.cpp (3032B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "nsDOMSerializer.h" 8 9 #include "mozilla/Encoding.h" 10 #include "mozilla/dom/Document.h" 11 #include "nsComponentManagerUtils.h" 12 #include "nsContentUtils.h" 13 #include "nsError.h" 14 #include "nsIDocumentEncoder.h" 15 #include "nsINode.h" 16 17 using namespace mozilla; 18 19 nsDOMSerializer::nsDOMSerializer() = default; 20 21 static already_AddRefed<nsIDocumentEncoder> SetUpEncoder( 22 nsINode& aRoot, const nsAString& aCharset, ErrorResult& aRv) { 23 nsCOMPtr<nsIDocumentEncoder> encoder = 24 do_createDocumentEncoder("application/xhtml+xml"); 25 if (!encoder) { 26 aRv.Throw(NS_ERROR_FAILURE); 27 return nullptr; 28 } 29 30 dom::Document* doc = aRoot.OwnerDoc(); 31 bool entireDocument = (doc == &aRoot); 32 33 // This method will fail if no document 34 nsresult rv = encoder->Init( 35 doc, u"application/xhtml+xml"_ns, 36 nsIDocumentEncoder::OutputRaw | 37 nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration); 38 39 if (NS_FAILED(rv)) { 40 aRv.Throw(rv); 41 return nullptr; 42 } 43 44 NS_ConvertUTF16toUTF8 charset(aCharset); 45 if (charset.IsEmpty()) { 46 doc->GetDocumentCharacterSet()->Name(charset); 47 } 48 rv = encoder->SetCharset(charset); 49 if (NS_FAILED(rv)) { 50 aRv.Throw(rv); 51 return nullptr; 52 } 53 54 // If we are working on the entire document we do not need to 55 // specify which part to serialize 56 if (!entireDocument) { 57 rv = encoder->SetNode(&aRoot); 58 } 59 60 if (NS_FAILED(rv)) { 61 aRv.Throw(rv); 62 return nullptr; 63 } 64 65 return encoder.forget(); 66 } 67 68 void nsDOMSerializer::SerializeToString(nsINode& aRoot, nsAString& aStr, 69 ErrorResult& aRv) { 70 aStr.Truncate(); 71 72 if (!nsContentUtils::CanCallerAccess(&aRoot)) { 73 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); 74 return; 75 } 76 77 nsCOMPtr<nsIDocumentEncoder> encoder = SetUpEncoder(aRoot, u""_ns, aRv); 78 if (aRv.Failed()) { 79 return; 80 } 81 82 nsresult rv = encoder->EncodeToString(aStr); 83 if (NS_FAILED(rv)) { 84 aRv.Throw(rv); 85 } 86 } 87 88 void nsDOMSerializer::SerializeToStream(nsINode& aRoot, 89 nsIOutputStream* aStream, 90 const nsAString& aCharset, 91 ErrorResult& aRv) { 92 if (NS_WARN_IF(!aStream)) { 93 aRv.Throw(NS_ERROR_INVALID_ARG); 94 return; 95 } 96 97 // The charset arg can be empty, in which case we get the document's 98 // charset and use that when serializing. 99 100 // No point doing a CanCallerAccess check, because we can only be 101 // called by system JS or C++. 102 nsCOMPtr<nsIDocumentEncoder> encoder = SetUpEncoder(aRoot, aCharset, aRv); 103 if (aRv.Failed()) { 104 return; 105 } 106 107 nsresult rv = encoder->EncodeToStream(aStream); 108 if (NS_FAILED(rv)) { 109 aRv.Throw(rv); 110 } 111 }