1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.dom;
16
17 import java.io.IOException;
18
19 import org.htmlunit.SgmlPage;
20 import org.htmlunit.StringWebResponse;
21 import org.htmlunit.WebClient;
22 import org.htmlunit.WebResponse;
23 import org.htmlunit.WebWindow;
24 import org.htmlunit.corejs.javascript.Context;
25 import org.htmlunit.corejs.javascript.Function;
26 import org.htmlunit.corejs.javascript.Scriptable;
27 import org.htmlunit.corejs.javascript.VarScope;
28 import org.htmlunit.html.DomDocumentType;
29 import org.htmlunit.html.Html;
30 import org.htmlunit.html.HtmlPage;
31 import org.htmlunit.html.parser.HTMLParser;
32 import org.htmlunit.javascript.HtmlUnitScriptable;
33 import org.htmlunit.javascript.JavaScriptEngine;
34 import org.htmlunit.javascript.configuration.JsxClass;
35 import org.htmlunit.javascript.configuration.JsxConstructor;
36 import org.htmlunit.javascript.configuration.JsxFunction;
37 import org.htmlunit.javascript.host.html.HTMLDocument;
38 import org.htmlunit.javascript.host.xml.XMLDocument;
39 import org.htmlunit.util.StringUtils;
40 import org.htmlunit.util.UrlUtils;
41 import org.htmlunit.xml.XmlPage;
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @JsxClass
56 public class DOMImplementation extends HtmlUnitScriptable {
57
58
59
60
61 @JsxConstructor
62 public void jsConstructor() {
63
64 }
65
66
67
68
69
70
71
72 @JsxFunction
73 public boolean hasFeature(final String feature, final String version) {
74 switch (feature) {
75 case "Core":
76 case "HTML":
77 case "XHTML":
78 case "XML":
79 switch (version) {
80 case "1.0":
81 case "2.0":
82 case "3.0":
83 return true;
84 default:
85 }
86 break;
87
88 case "Views":
89 switch (version) {
90 case "1.0":
91 case "2.0":
92 case "3.0":
93 return true;
94 default:
95 }
96 break;
97
98 case "StyleSheets":
99 case "KeyboardEvents":
100 case "MutationNameEvents":
101 case "TextEvents":
102 case "LS":
103 case "LS-Async":
104 case "Validation":
105 case "XPath":
106 return true;
107
108 case "CSS":
109 switch (version) {
110 case "1.0":
111 case "2.0":
112 case "3.0":
113 return true;
114 default:
115 }
116 break;
117
118 case "CSS2":
119 switch (version) {
120 case "1.0":
121 case "2.0":
122 case "3.0":
123 return true;
124 default:
125 }
126 break;
127
128 case "CSS3":
129 switch (version) {
130 case "1.0":
131 case "2.0":
132 case "3.0":
133 return true;
134 default:
135 }
136 break;
137
138 case "Events":
139 case "HTMLEvents":
140 case "MouseEvents":
141 case "MutationEvents":
142 switch (version) {
143 case "1.0":
144 case "2.0":
145 case "3.0":
146 return true;
147 default:
148 }
149 break;
150
151 case "UIEvents":
152 switch (version) {
153 case "1.0":
154 case "2.0":
155 case "3.0":
156 return true;
157 default:
158 }
159 break;
160
161 case "Range":
162 case "Traversal":
163 switch (version) {
164 case "1.0":
165 case "2.0":
166 case "3.0":
167 return true;
168 default:
169 }
170 break;
171
172 case "http://www.w3.org/TR/SVG11/feature#BasicStructure":
173 case "http://www.w3.org/TR/SVG11/feature#Shape":
174 switch (version) {
175 case "1.0":
176 case "1.1":
177 case "1.2":
178 return true;
179 default:
180 }
181 break;
182
183 default:
184 }
185
186 return false;
187 }
188
189
190
191
192
193
194
195
196
197 @JsxFunction
198 public XMLDocument createDocument(final Object namespaceURI, final String qualifiedName,
199 final DocumentType doctype) {
200
201 final String namespace;
202 if (namespaceURI == null || JavaScriptEngine.isUndefined(namespaceURI)) {
203 namespace = null;
204 }
205 else {
206 namespace = JavaScriptEngine.toString(namespaceURI);
207 }
208
209 final XMLDocument document = new XMLDocument(getWindow().getWebWindow());
210 document.setParentScope(getParentScope());
211 document.setPrototype(getPrototype(document.getClass()));
212
213 final XmlPage page = (XmlPage) document.getDomNodeOrDie();
214 if (doctype != null) {
215
216 final DomDocumentType doctypeNode = (DomDocumentType) doctype.getDomNodeOrDie();
217 page.appendChild(doctypeNode);
218 page.setDocumentType(doctypeNode);
219 }
220 if (qualifiedName != null && !qualifiedName.isEmpty()) {
221 page.appendChild(page.createElementNS(
222 StringUtils.isEmptyString(namespace) ? null : namespace, qualifiedName));
223 }
224 return document;
225 }
226
227
228
229
230
231
232
233
234
235
236
237
238
239 @JsxFunction
240 public static DocumentType createDocumentType(final Context context, final VarScope scope,
241 final Scriptable thisObj, final Object[] args, final Function function) {
242 if (args.length < 3) {
243 throw JavaScriptEngine.typeError("Failed to execute 'createDocumentType' on 'DOMImplementation': "
244 + "3 arguments required, but only " + args.length + " present.");
245 }
246
247 final DOMImplementation implementation = (DOMImplementation) thisObj;
248 final String qualifiedName = JavaScriptEngine.toString(args[0]);
249 final String publicId = JavaScriptEngine.toString(args[1]);
250 final String systemId = JavaScriptEngine.toString(args[2]);
251
252 if (!isValidDocumentTypeName(qualifiedName)) {
253 throw JavaScriptEngine.asJavaScriptException(
254 implementation.getWindow(),
255 "createDocumentType: Provided string '" + qualifiedName + "' contains an invalid character",
256 DOMException.INVALID_CHARACTER_ERR);
257 }
258
259
260
261 final SgmlPage page = (SgmlPage) implementation.getWindow().getWebWindow().getEnclosedPage();
262 final DomDocumentType doctype = new DomDocumentType(page, qualifiedName, publicId, systemId);
263 return (DocumentType) implementation.getScriptableFor(doctype);
264 }
265
266
267
268
269
270 private static boolean isValidDocumentTypeName(final String name) {
271 final int length = name.length();
272 for (int i = 0; i < length; i++) {
273 final char c = name.charAt(i);
274 if (c == '>' || c == '\u0000'
275 || c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r') {
276 return false;
277 }
278 }
279 return true;
280 }
281
282
283
284
285
286
287
288
289
290 @JsxFunction
291 public HTMLDocument createHTMLDocument(final Object titleObj) {
292
293
294 try {
295 final WebWindow webWindow = getWindow().getWebWindow();
296 final String html;
297 if (JavaScriptEngine.isUndefined(titleObj)) {
298 html = Html.DOCTYPE_HTML + "<html><head></head><body></body></html>";
299 }
300 else {
301 html = Html.DOCTYPE_HTML
302 + "<html><head><title>"
303 + JavaScriptEngine.toString(titleObj)
304 + "</title></head><body></body></html>";
305 }
306 final WebResponse webResponse = new StringWebResponse(html, UrlUtils.URL_ABOUT_BLANK);
307 final HtmlPage page = new HtmlPage(webResponse, webWindow);
308
309
310 page.setEnclosingWindow(null);
311
312
313 final HTMLDocument document = new HTMLDocument();
314 document.setParentScope(getTopLevelScope(getParentScope()));
315 document.setPrototype(getPrototype(document.getClass()));
316
317 document.setDomNode(page);
318
319 final WebClient webClient = webWindow.getWebClient();
320 final HTMLParser htmlParser = webClient.getPageCreator().getHtmlParser();
321 htmlParser.parse(webClient, webResponse, page, false, false);
322 return page.getScriptableObject();
323 }
324 catch (final IOException e) {
325 throw JavaScriptEngine.reportRuntimeError("Parsing failed" + e.getMessage());
326 }
327 }
328 }