|
1 /* -*- Mode: C++; tab-width: 2; 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 "nsDOMSerializer.h" |
|
7 |
|
8 #include "nsIDocument.h" |
|
9 #include "nsIDocumentEncoder.h" |
|
10 #include "nsIDOMDocument.h" |
|
11 #include "nsComponentManagerUtils.h" |
|
12 #include "nsContentCID.h" |
|
13 #include "nsContentUtils.h" |
|
14 #include "nsError.h" |
|
15 #include "nsINode.h" |
|
16 |
|
17 using namespace mozilla; |
|
18 |
|
19 nsDOMSerializer::nsDOMSerializer() |
|
20 { |
|
21 SetIsDOMBinding(); |
|
22 } |
|
23 |
|
24 nsDOMSerializer::~nsDOMSerializer() |
|
25 { |
|
26 } |
|
27 |
|
28 // QueryInterface implementation for nsDOMSerializer |
|
29 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMSerializer) |
|
30 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY |
|
31 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
32 NS_INTERFACE_MAP_ENTRY(nsIDOMSerializer) |
|
33 NS_INTERFACE_MAP_END |
|
34 |
|
35 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsDOMSerializer, mOwner) |
|
36 |
|
37 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMSerializer) |
|
38 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMSerializer) |
|
39 |
|
40 |
|
41 static nsresult |
|
42 SetUpEncoder(nsIDOMNode *aRoot, const nsACString& aCharset, |
|
43 nsIDocumentEncoder **aEncoder) |
|
44 { |
|
45 *aEncoder = nullptr; |
|
46 |
|
47 nsresult rv; |
|
48 nsCOMPtr<nsIDocumentEncoder> encoder = |
|
49 do_CreateInstance(NS_DOC_ENCODER_CONTRACTID_BASE "application/xhtml+xml", &rv); |
|
50 if (NS_FAILED(rv)) |
|
51 return rv; |
|
52 |
|
53 bool entireDocument = true; |
|
54 nsCOMPtr<nsIDOMDocument> domDoc(do_QueryInterface(aRoot)); |
|
55 if (!domDoc) { |
|
56 entireDocument = false; |
|
57 rv = aRoot->GetOwnerDocument(getter_AddRefs(domDoc)); |
|
58 if (NS_FAILED(rv)) |
|
59 return rv; |
|
60 } |
|
61 |
|
62 // This method will fail if no document |
|
63 rv = encoder->Init(domDoc, NS_LITERAL_STRING("application/xhtml+xml"), |
|
64 nsIDocumentEncoder::OutputRaw | |
|
65 nsIDocumentEncoder::OutputDontRewriteEncodingDeclaration); |
|
66 |
|
67 if (NS_FAILED(rv)) |
|
68 return rv; |
|
69 |
|
70 nsAutoCString charset(aCharset); |
|
71 if (charset.IsEmpty()) { |
|
72 nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc); |
|
73 NS_ASSERTION(doc, "Need a document"); |
|
74 charset = doc->GetDocumentCharacterSet(); |
|
75 } |
|
76 rv = encoder->SetCharset(charset); |
|
77 if (NS_FAILED(rv)) |
|
78 return rv; |
|
79 |
|
80 // If we are working on the entire document we do not need to |
|
81 // specify which part to serialize |
|
82 if (!entireDocument) { |
|
83 rv = encoder->SetNode(aRoot); |
|
84 } |
|
85 |
|
86 if (NS_SUCCEEDED(rv)) { |
|
87 *aEncoder = encoder.get(); |
|
88 NS_ADDREF(*aEncoder); |
|
89 } |
|
90 |
|
91 return rv; |
|
92 } |
|
93 |
|
94 void |
|
95 nsDOMSerializer::SerializeToString(nsINode& aRoot, nsAString& aStr, |
|
96 ErrorResult& rv) |
|
97 { |
|
98 rv = nsDOMSerializer::SerializeToString(aRoot.AsDOMNode(), aStr); |
|
99 } |
|
100 |
|
101 NS_IMETHODIMP |
|
102 nsDOMSerializer::SerializeToString(nsIDOMNode *aRoot, nsAString& _retval) |
|
103 { |
|
104 NS_ENSURE_ARG_POINTER(aRoot); |
|
105 |
|
106 _retval.Truncate(); |
|
107 |
|
108 if (!nsContentUtils::CanCallerAccess(aRoot)) { |
|
109 return NS_ERROR_DOM_SECURITY_ERR; |
|
110 } |
|
111 |
|
112 nsCOMPtr<nsIDocumentEncoder> encoder; |
|
113 nsresult rv = SetUpEncoder(aRoot, EmptyCString(), getter_AddRefs(encoder)); |
|
114 if (NS_FAILED(rv)) |
|
115 return rv; |
|
116 |
|
117 return encoder->EncodeToString(_retval); |
|
118 } |
|
119 |
|
120 void |
|
121 nsDOMSerializer::SerializeToStream(nsINode& aRoot, nsIOutputStream* aStream, |
|
122 const nsAString& aCharset, ErrorResult& rv) |
|
123 { |
|
124 rv = nsDOMSerializer::SerializeToStream(aRoot.AsDOMNode(), aStream, |
|
125 NS_ConvertUTF16toUTF8(aCharset)); |
|
126 } |
|
127 |
|
128 NS_IMETHODIMP |
|
129 nsDOMSerializer::SerializeToStream(nsIDOMNode *aRoot, |
|
130 nsIOutputStream *aStream, |
|
131 const nsACString& aCharset) |
|
132 { |
|
133 NS_ENSURE_ARG_POINTER(aRoot); |
|
134 NS_ENSURE_ARG_POINTER(aStream); |
|
135 // The charset arg can be empty, in which case we get the document's |
|
136 // charset and use that when serializing. |
|
137 |
|
138 if (!nsContentUtils::CanCallerAccess(aRoot)) { |
|
139 return NS_ERROR_DOM_SECURITY_ERR; |
|
140 } |
|
141 |
|
142 nsCOMPtr<nsIDocumentEncoder> encoder; |
|
143 nsresult rv = SetUpEncoder(aRoot, aCharset, getter_AddRefs(encoder)); |
|
144 if (NS_FAILED(rv)) |
|
145 return rv; |
|
146 |
|
147 return encoder->EncodeToStream(aStream); |
|
148 } |