|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "mozilla/dom/DOMImplementation.h" |
|
6 |
|
7 #include "mozilla/ContentEvents.h" |
|
8 #include "mozilla/dom/DOMImplementationBinding.h" |
|
9 #include "nsContentCreatorFunctions.h" |
|
10 #include "nsContentUtils.h" |
|
11 #include "nsDOMClassInfoID.h" |
|
12 #include "nsIDOMDocument.h" |
|
13 #include "DocumentType.h" |
|
14 #include "nsTextNode.h" |
|
15 |
|
16 namespace mozilla { |
|
17 namespace dom { |
|
18 |
|
19 // QueryInterface implementation for DOMImplementation |
|
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMImplementation) |
|
21 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY |
|
22 NS_INTERFACE_MAP_ENTRY(nsIDOMDOMImplementation) |
|
23 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
24 NS_INTERFACE_MAP_END |
|
25 |
|
26 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(DOMImplementation, mOwner) |
|
27 |
|
28 NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMImplementation) |
|
29 NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMImplementation) |
|
30 |
|
31 JSObject* |
|
32 DOMImplementation::WrapObject(JSContext* aCx) |
|
33 { |
|
34 return DOMImplementationBinding::Wrap(aCx, this); |
|
35 } |
|
36 |
|
37 bool |
|
38 DOMImplementation::HasFeature(const nsAString& aFeature, |
|
39 const nsAString& aVersion) |
|
40 { |
|
41 return nsContentUtils::InternalIsSupported( |
|
42 static_cast<nsIDOMDOMImplementation*>(this), |
|
43 aFeature, aVersion); |
|
44 } |
|
45 |
|
46 NS_IMETHODIMP |
|
47 DOMImplementation::HasFeature(const nsAString& aFeature, |
|
48 const nsAString& aVersion, |
|
49 bool* aReturn) |
|
50 { |
|
51 *aReturn = HasFeature(aFeature, aVersion); |
|
52 return NS_OK; |
|
53 } |
|
54 |
|
55 already_AddRefed<DocumentType> |
|
56 DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName, |
|
57 const nsAString& aPublicId, |
|
58 const nsAString& aSystemId, |
|
59 ErrorResult& aRv) |
|
60 { |
|
61 if (!mOwner) { |
|
62 aRv.Throw(NS_ERROR_UNEXPECTED); |
|
63 return nullptr; |
|
64 } |
|
65 |
|
66 aRv = nsContentUtils::CheckQName(aQualifiedName); |
|
67 if (aRv.Failed()) { |
|
68 return nullptr; |
|
69 } |
|
70 |
|
71 nsCOMPtr<nsIAtom> name = do_GetAtom(aQualifiedName); |
|
72 if (!name) { |
|
73 aRv.Throw(NS_ERROR_OUT_OF_MEMORY); |
|
74 return nullptr; |
|
75 } |
|
76 |
|
77 // Indicate that there is no internal subset (not just an empty one) |
|
78 nsRefPtr<DocumentType> docType = |
|
79 NS_NewDOMDocumentType(mOwner->NodeInfoManager(), name, aPublicId, |
|
80 aSystemId, NullString(), aRv); |
|
81 return docType.forget(); |
|
82 } |
|
83 |
|
84 NS_IMETHODIMP |
|
85 DOMImplementation::CreateDocumentType(const nsAString& aQualifiedName, |
|
86 const nsAString& aPublicId, |
|
87 const nsAString& aSystemId, |
|
88 nsIDOMDocumentType** aReturn) |
|
89 { |
|
90 ErrorResult rv; |
|
91 *aReturn = |
|
92 CreateDocumentType(aQualifiedName, aPublicId, aSystemId, rv).take(); |
|
93 return rv.ErrorCode(); |
|
94 } |
|
95 |
|
96 nsresult |
|
97 DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, |
|
98 const nsAString& aQualifiedName, |
|
99 nsIDOMDocumentType* aDoctype, |
|
100 nsIDocument** aDocument, |
|
101 nsIDOMDocument** aDOMDocument) |
|
102 { |
|
103 *aDocument = nullptr; |
|
104 *aDOMDocument = nullptr; |
|
105 |
|
106 nsresult rv; |
|
107 if (!aQualifiedName.IsEmpty()) { |
|
108 const nsAFlatString& qName = PromiseFlatString(aQualifiedName); |
|
109 const char16_t *colon; |
|
110 rv = nsContentUtils::CheckQName(qName, true, &colon); |
|
111 NS_ENSURE_SUCCESS(rv, rv); |
|
112 |
|
113 if (colon && |
|
114 (DOMStringIsNull(aNamespaceURI) || |
|
115 (Substring(qName.get(), colon).EqualsLiteral("xml") && |
|
116 !aNamespaceURI.EqualsLiteral("http://www.w3.org/XML/1998/namespace")))) { |
|
117 return NS_ERROR_DOM_NAMESPACE_ERR; |
|
118 } |
|
119 } |
|
120 |
|
121 nsCOMPtr<nsIGlobalObject> scriptHandlingObject = |
|
122 do_QueryReferent(mScriptObject); |
|
123 |
|
124 NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); |
|
125 |
|
126 nsCOMPtr<nsIDOMDocument> document; |
|
127 |
|
128 rv = NS_NewDOMDocument(getter_AddRefs(document), |
|
129 aNamespaceURI, aQualifiedName, aDoctype, |
|
130 mDocumentURI, mBaseURI, |
|
131 mOwner->NodePrincipal(), |
|
132 true, scriptHandlingObject, |
|
133 DocumentFlavorLegacyGuess); |
|
134 NS_ENSURE_SUCCESS(rv, rv); |
|
135 |
|
136 // When DOMImplementation's createDocument method is invoked with |
|
137 // namespace set to HTML Namespace use the registry of the associated |
|
138 // document to the new instance. |
|
139 nsCOMPtr<nsIDocument> doc = do_QueryInterface(document); |
|
140 if (aNamespaceURI.EqualsLiteral("http://www.w3.org/1999/xhtml")) { |
|
141 doc->UseRegistryFromDocument(mOwner); |
|
142 } |
|
143 |
|
144 doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); |
|
145 |
|
146 doc.forget(aDocument); |
|
147 document.forget(aDOMDocument); |
|
148 return NS_OK; |
|
149 } |
|
150 |
|
151 already_AddRefed<nsIDocument> |
|
152 DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, |
|
153 const nsAString& aQualifiedName, |
|
154 nsIDOMDocumentType* aDoctype, |
|
155 ErrorResult& aRv) |
|
156 { |
|
157 nsCOMPtr<nsIDocument> document; |
|
158 nsCOMPtr<nsIDOMDocument> domDocument; |
|
159 aRv = CreateDocument(aNamespaceURI, aQualifiedName, aDoctype, |
|
160 getter_AddRefs(document), getter_AddRefs(domDocument)); |
|
161 return document.forget(); |
|
162 } |
|
163 |
|
164 NS_IMETHODIMP |
|
165 DOMImplementation::CreateDocument(const nsAString& aNamespaceURI, |
|
166 const nsAString& aQualifiedName, |
|
167 nsIDOMDocumentType* aDoctype, |
|
168 nsIDOMDocument** aReturn) |
|
169 { |
|
170 nsCOMPtr<nsIDocument> document; |
|
171 return CreateDocument(aNamespaceURI, aQualifiedName, aDoctype, |
|
172 getter_AddRefs(document), aReturn); |
|
173 } |
|
174 |
|
175 nsresult |
|
176 DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, |
|
177 nsIDocument** aDocument, |
|
178 nsIDOMDocument** aDOMDocument) |
|
179 { |
|
180 *aDocument = nullptr; |
|
181 *aDOMDocument = nullptr; |
|
182 |
|
183 NS_ENSURE_STATE(mOwner); |
|
184 |
|
185 nsCOMPtr<nsIDOMDocumentType> doctype; |
|
186 // Indicate that there is no internal subset (not just an empty one) |
|
187 nsresult rv = NS_NewDOMDocumentType(getter_AddRefs(doctype), |
|
188 mOwner->NodeInfoManager(), |
|
189 nsGkAtoms::html, // aName |
|
190 EmptyString(), // aPublicId |
|
191 EmptyString(), // aSystemId |
|
192 NullString()); // aInternalSubset |
|
193 NS_ENSURE_SUCCESS(rv, rv); |
|
194 |
|
195 |
|
196 nsCOMPtr<nsIGlobalObject> scriptHandlingObject = |
|
197 do_QueryReferent(mScriptObject); |
|
198 |
|
199 NS_ENSURE_STATE(!mScriptObject || scriptHandlingObject); |
|
200 |
|
201 nsCOMPtr<nsIDOMDocument> document; |
|
202 rv = NS_NewDOMDocument(getter_AddRefs(document), |
|
203 EmptyString(), EmptyString(), |
|
204 doctype, mDocumentURI, mBaseURI, |
|
205 mOwner->NodePrincipal(), |
|
206 true, scriptHandlingObject, |
|
207 DocumentFlavorLegacyGuess); |
|
208 NS_ENSURE_SUCCESS(rv, rv); |
|
209 nsCOMPtr<nsIDocument> doc = do_QueryInterface(document); |
|
210 |
|
211 nsCOMPtr<nsIContent> root; |
|
212 rv = doc->CreateElem(NS_LITERAL_STRING("html"), nullptr, kNameSpaceID_XHTML, |
|
213 getter_AddRefs(root)); |
|
214 NS_ENSURE_SUCCESS(rv, rv); |
|
215 rv = doc->AppendChildTo(root, false); |
|
216 NS_ENSURE_SUCCESS(rv, rv); |
|
217 |
|
218 nsCOMPtr<nsIContent> head; |
|
219 rv = doc->CreateElem(NS_LITERAL_STRING("head"), nullptr, kNameSpaceID_XHTML, |
|
220 getter_AddRefs(head)); |
|
221 NS_ENSURE_SUCCESS(rv, rv); |
|
222 rv = root->AppendChildTo(head, false); |
|
223 NS_ENSURE_SUCCESS(rv, rv); |
|
224 |
|
225 if (!DOMStringIsNull(aTitle)) { |
|
226 nsCOMPtr<nsIContent> title; |
|
227 rv = doc->CreateElem(NS_LITERAL_STRING("title"), nullptr, |
|
228 kNameSpaceID_XHTML, getter_AddRefs(title)); |
|
229 NS_ENSURE_SUCCESS(rv, rv); |
|
230 rv = head->AppendChildTo(title, false); |
|
231 NS_ENSURE_SUCCESS(rv, rv); |
|
232 |
|
233 nsRefPtr<nsTextNode> titleText = new nsTextNode(doc->NodeInfoManager()); |
|
234 rv = titleText->SetText(aTitle, false); |
|
235 NS_ENSURE_SUCCESS(rv, rv); |
|
236 rv = title->AppendChildTo(titleText, false); |
|
237 NS_ENSURE_SUCCESS(rv, rv); |
|
238 } |
|
239 |
|
240 nsCOMPtr<nsIContent> body; |
|
241 rv = doc->CreateElem(NS_LITERAL_STRING("body"), nullptr, kNameSpaceID_XHTML, |
|
242 getter_AddRefs(body)); |
|
243 NS_ENSURE_SUCCESS(rv, rv); |
|
244 rv = root->AppendChildTo(body, false); |
|
245 NS_ENSURE_SUCCESS(rv, rv); |
|
246 |
|
247 // When the createHTMLDocument method is invoked, |
|
248 // use the registry of the associated document to the new instance. |
|
249 doc->UseRegistryFromDocument(mOwner); |
|
250 |
|
251 doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE); |
|
252 |
|
253 doc.forget(aDocument); |
|
254 document.forget(aDOMDocument); |
|
255 return NS_OK; |
|
256 } |
|
257 |
|
258 already_AddRefed<nsIDocument> |
|
259 DOMImplementation::CreateHTMLDocument(const Optional<nsAString>& aTitle, |
|
260 ErrorResult& aRv) |
|
261 { |
|
262 nsCOMPtr<nsIDocument> document; |
|
263 nsCOMPtr<nsIDOMDocument> domDocument; |
|
264 aRv = CreateHTMLDocument(aTitle.WasPassed() ? aTitle.Value() |
|
265 : NullString(), |
|
266 getter_AddRefs(document), |
|
267 getter_AddRefs(domDocument)); |
|
268 return document.forget(); |
|
269 } |
|
270 |
|
271 NS_IMETHODIMP |
|
272 DOMImplementation::CreateHTMLDocument(const nsAString& aTitle, |
|
273 nsIDOMDocument** aReturn) |
|
274 { |
|
275 nsCOMPtr<nsIDocument> document; |
|
276 return CreateHTMLDocument(aTitle, getter_AddRefs(document), aReturn); |
|
277 } |
|
278 |
|
279 } // namespace dom |
|
280 } // namespace mozilla |