2008-11-04 Anders Carlsson <andersca@apple.com>
[webkit/qt.git] / WebCore / dom / DOMImplementation.cpp
blobd7a89031f46fab0f9f2411e43271a607e09ff8ca
1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
24 #include "config.h"
25 #include "DOMImplementation.h"
27 #include "CSSStyleSheet.h"
28 #include "DocumentType.h"
29 #include "Element.h"
30 #include "ExceptionCode.h"
31 #include "Frame.h"
32 #include "FTPDirectoryDocument.h"
33 #include "HTMLDocument.h"
34 #include "HTMLNames.h"
35 #include "HTMLViewSourceDocument.h"
36 #include "Image.h"
37 #include "ImageDocument.h"
38 #include "MediaDocument.h"
39 #include "MediaList.h"
40 #include "MediaPlayer.h"
41 #include "MIMETypeRegistry.h"
42 #include "Page.h"
43 #include "PluginData.h"
44 #include "PluginDocument.h"
45 #include "RegularExpression.h"
46 #include "Settings.h"
47 #include "TextDocument.h"
48 #include "XMLNames.h"
50 #if ENABLE(SVG)
51 #include "SVGNames.h"
52 #include "SVGDocument.h"
53 #endif
55 namespace WebCore {
57 #if ENABLE(SVG)
59 static void addString(HashSet<String, CaseFoldingHash>& set, const char* string)
61 set.add(string);
64 static bool isSVG10Feature(const String &feature)
66 static bool initialized = false;
67 static HashSet<String, CaseFoldingHash> svgFeatures;
68 if (!initialized) {
69 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(SVG_FILTER) && ENABLE(SVG_FONTS)
70 addString(svgFeatures, "svg");
71 addString(svgFeatures, "svg.static");
72 #endif
73 // addString(svgFeatures, "svg.animation");
74 // addString(svgFeatures, "svg.dynamic");
75 // addString(svgFeatures, "svg.dom.animation");
76 // addString(svgFeatures, "svg.dom.dynamic");
77 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(SVG_FILTER) && ENABLE(SVG_FONTS)
78 addString(svgFeatures, "dom");
79 addString(svgFeatures, "dom.svg");
80 addString(svgFeatures, "dom.svg.static");
81 #endif
82 // addString(svgFeatures, "svg.all");
83 // addString(svgFeatures, "dom.svg.all");
84 initialized = true;
86 return svgFeatures.contains(feature);
89 static bool isSVG11Feature(const String &feature)
91 static bool initialized = false;
92 static HashSet<String, CaseFoldingHash> svgFeatures;
93 if (!initialized) {
94 // Sadly, we cannot claim to implement any of the SVG 1.1 generic feature sets
95 // lack of Font and Filter support.
96 // http://bugs.webkit.org/show_bug.cgi?id=15480
97 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(SVG_FILTER) && ENABLE(SVG_FONTS)
98 addString(svgFeatures, "SVG");
99 addString(svgFeatures, "SVGDOM");
100 addString(svgFeatures, "SVG-static");
101 addString(svgFeatures, "SVGDOM-static");
102 #endif
103 #if ENABLE(SVG_ANIMATION)
104 addString(svgFeatures, "SVG-animation");
105 addString(svgFeatures, "SVGDOM-animation");
106 #endif
107 // addString(svgFeatures, "SVG-dynamic);
108 // addString(svgFeatures, "SVGDOM-dynamic);
109 addString(svgFeatures, "CoreAttribute");
110 #if ENABLE(SVG_USE)
111 addString(svgFeatures, "Structure");
112 addString(svgFeatures, "BasicStructure");
113 #endif
114 addString(svgFeatures, "ContainerAttribute");
115 addString(svgFeatures, "ConditionalProcessing");
116 addString(svgFeatures, "Image");
117 addString(svgFeatures, "Style");
118 addString(svgFeatures, "ViewportAttribute");
119 addString(svgFeatures, "Shape");
120 // addString(svgFeatures, "Text"); // requires altGlyph, bug 6426
121 addString(svgFeatures, "BasicText");
122 addString(svgFeatures, "PaintAttribute");
123 addString(svgFeatures, "BasicPaintAttribute");
124 addString(svgFeatures, "OpacityAttribute");
125 addString(svgFeatures, "GraphicsAttribute");
126 addString(svgFeatures, "BaseGraphicsAttribute");
127 addString(svgFeatures, "Marker");
128 // addString(svgFeatures, "ColorProfile"); // requires color-profile, bug 6037
129 addString(svgFeatures, "Gradient");
130 addString(svgFeatures, "Pattern");
131 addString(svgFeatures, "Clip");
132 addString(svgFeatures, "BasicClip");
133 addString(svgFeatures, "Mask");
134 #if ENABLE(SVG_FILTER)
135 // addString(svgFeatures, "Filter");
136 addString(svgFeatures, "BasicFilter");
137 #endif
138 addString(svgFeatures, "DocumentEventsAttribute");
139 addString(svgFeatures, "GraphicalEventsAttribute");
140 // addString(svgFeatures, "AnimationEventsAttribute");
141 addString(svgFeatures, "Cursor");
142 addString(svgFeatures, "Hyperlinking");
143 addString(svgFeatures, "XlinkAttribute");
144 addString(svgFeatures, "ExternalResourcesRequired");
145 // addString(svgFeatures, "View"); // buggy <view> support, bug 16962
146 addString(svgFeatures, "Script");
147 #if ENABLE(SVG_ANIMATION)
148 addString(svgFeatures, "Animation");
149 #endif
150 #if ENABLE(SVG_FONTS)
151 addString(svgFeatures, "Font");
152 addString(svgFeatures, "BasicFont");
153 #endif
154 #if ENABLE(SVG_FOREIGN_OBJECT)
155 addString(svgFeatures, "Extensibility");
156 #endif
157 initialized = true;
159 return svgFeatures.contains(feature);
161 #endif
163 bool DOMImplementation::hasFeature(const String& feature, const String& version)
165 String lower = feature.lower();
166 if (lower == "core" || lower == "html" || lower == "xml" || lower == "xhtml")
167 return version.isEmpty() || version == "1.0" || version == "2.0";
168 if (lower == "css"
169 || lower == "css2"
170 || lower == "events"
171 || lower == "htmlevents"
172 || lower == "mouseevents"
173 || lower == "mutationevents"
174 || lower == "range"
175 || lower == "stylesheets"
176 || lower == "traversal"
177 || lower == "uievents"
178 || lower == "views")
179 return version.isEmpty() || version == "2.0";
180 if (lower == "xpath" || lower == "textevents")
181 return version.isEmpty() || version == "3.0";
183 #if ENABLE(SVG)
184 if ((version.isEmpty() || version == "1.1") && feature.startsWith("http://www.w3.org/tr/svg11/feature#", false)) {
185 if (isSVG11Feature(feature.right(feature.length() - 35)))
186 return true;
189 if ((version.isEmpty() || version == "1.0") && feature.startsWith("org.w3c.", false)) {
190 if (isSVG10Feature(feature.right(feature.length() - 8)))
191 return true;
193 #endif
195 return false;
198 PassRefPtr<DocumentType> DOMImplementation::createDocumentType(const String& qualifiedName,
199 const String& publicId, const String& systemId, ExceptionCode& ec)
201 String prefix, localName;
202 if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
203 return 0;
205 return DocumentType::create(0, qualifiedName, publicId, systemId);
208 DOMImplementation* DOMImplementation::getInterface(const String& /*feature*/)
210 return 0;
213 PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceURI,
214 const String& qualifiedName, DocumentType* doctype, ExceptionCode& ec)
216 // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
217 // created from a different implementation.
218 bool shouldThrowWrongDocErr = false;
219 if (doctype && doctype->document())
220 shouldThrowWrongDocErr = true;
222 RefPtr<Document> doc;
223 #if ENABLE(SVG)
224 if (namespaceURI == SVGNames::svgNamespaceURI)
225 doc = SVGDocument::create(0);
226 else
227 #endif
228 if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
229 doc = Document::createXHTML(0);
230 else
231 doc = Document::create(0);
233 // now get the interesting parts of the doctype
234 if (doctype)
235 doc->addChild(doctype);
237 if (!qualifiedName.isEmpty()) {
238 doc->addChild(doc->createElementNS(namespaceURI, qualifiedName, ec));
239 if (ec != 0)
240 return 0;
243 // Hixie's interpretation of the DOM Core spec suggests we should prefer
244 // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec)
245 if (shouldThrowWrongDocErr) {
246 ec = WRONG_DOCUMENT_ERR;
247 return 0;
250 return doc.release();
253 PassRefPtr<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&, const String& media, ExceptionCode&)
255 // FIXME: Title should be set.
256 // FIXME: Media could have wrong syntax, in which case we should generate an exception.
257 RefPtr<CSSStyleSheet> sheet = CSSStyleSheet::create();
258 sheet->setMedia(MediaList::createAllowingDescriptionSyntax(sheet.get(), media));
259 return sheet.release();
262 PassRefPtr<Document> DOMImplementation::createDocument(Frame* frame)
264 return Document::create(frame);
267 PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(Frame* frame)
269 return HTMLDocument::create(frame);
272 bool DOMImplementation::isXMLMIMEType(const String& mimeType)
274 if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
275 return true;
276 static const char* validChars = "[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]"; // per RFCs: 3023, 2045
277 static RegularExpression xmlTypeRegExp(String("^") + validChars + "+/" + validChars + "+\\+xml$");
278 return xmlTypeRegExp.match(mimeType) > -1;
281 bool DOMImplementation::isTextMIMEType(const String& mimeType)
283 if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) ||
284 (mimeType.startsWith("text/") && mimeType != "text/html" &&
285 mimeType != "text/xml" && mimeType != "text/xsl"))
286 return true;
288 return false;
291 PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& title)
293 RefPtr<HTMLDocument> d = HTMLDocument::create(0);
294 d->open();
295 d->write("<!doctype html><html><head><title>" + title + "</title></head><body></body></html>");
296 return d.release();
299 PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, bool inViewSourceMode)
301 if (inViewSourceMode) {
302 if (type == "text/html" || type == "application/xhtml+xml" || type == "image/svg+xml" || isTextMIMEType(type) || isXMLMIMEType(type))
303 return HTMLViewSourceDocument::create(frame, type);
306 // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those.
307 if (type == "text/html")
308 return HTMLDocument::create(frame);
309 if (type == "application/xhtml+xml")
310 return Document::createXHTML(frame);
312 #if ENABLE(FTPDIR)
313 // Plugins cannot take FTP from us either
314 if (type == "application/x-ftp-directory")
315 return FTPDirectoryDocument::create(frame);
316 #endif
318 PluginData* pluginData = 0;
319 if (frame && frame->page() && frame->page()->settings()->arePluginsEnabled())
320 pluginData = frame->page()->pluginData();
322 // PDF is one image type for which a plugin can override built-in support.
323 // We do not want QuickTime to take over all image types, obviously.
324 if ((type == "application/pdf" || type == "text/pdf") && pluginData && pluginData->supportsMimeType(type))
325 return PluginDocument::create(frame);
326 if (Image::supportsType(type))
327 return ImageDocument::create(frame);
329 #if ENABLE(VIDEO)
330 // Check to see if the type can be played by our MediaPlayer, if so create a MediaDocument
331 if (MediaPlayer::supportsType(type))
332 return MediaDocument::create(frame);
333 #endif
335 // Everything else except text/plain can be overridden by plugins. In particular, Adobe SVG Viewer should be used for SVG, if installed.
336 // Disallowing plug-ins to use text/plain prevents plug-ins from hijacking a fundamental type that the browser is expected to handle,
337 // and also serves as an optimization to prevent loading the plug-in database in the common case.
338 if (type != "text/plain" && pluginData && pluginData->supportsMimeType(type))
339 return PluginDocument::create(frame);
340 if (isTextMIMEType(type))
341 return TextDocument::create(frame);
343 #if ENABLE(SVG)
344 if (type == "image/svg+xml") {
345 #if ENABLE(DASHBOARD_SUPPORT)
346 Settings* settings = frame ? frame->settings() : 0;
347 if (!settings || !settings->usesDashboardBackwardCompatibilityMode())
348 #endif
349 return SVGDocument::create(frame);
351 #endif
352 if (isXMLMIMEType(type))
353 return Document::create(frame);
355 return HTMLDocument::create(frame);