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.
25 #include "DOMImplementation.h"
27 #include "CSSStyleSheet.h"
28 #include "DocumentType.h"
30 #include "ExceptionCode.h"
32 #include "FTPDirectoryDocument.h"
33 #include "HTMLDocument.h"
34 #include "HTMLNames.h"
35 #include "HTMLViewSourceDocument.h"
37 #include "ImageDocument.h"
38 #include "MediaDocument.h"
39 #include "MediaList.h"
40 #include "MediaPlayer.h"
41 #include "MIMETypeRegistry.h"
43 #include "PluginData.h"
44 #include "PluginDocument.h"
45 #include "RegularExpression.h"
47 #include "TextDocument.h"
52 #include "SVGDocument.h"
59 static void addString(HashSet
<String
, CaseFoldingHash
>& set
, const char* string
)
64 static bool isSVG10Feature(const String
&feature
)
66 static bool initialized
= false;
67 static HashSet
<String
, CaseFoldingHash
> svgFeatures
;
69 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(SVG_FILTER) && ENABLE(SVG_FONTS)
70 addString(svgFeatures
, "svg");
71 addString(svgFeatures
, "svg.static");
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");
82 // addString(svgFeatures, "svg.all");
83 // addString(svgFeatures, "dom.svg.all");
86 return svgFeatures
.contains(feature
);
89 static bool isSVG11Feature(const String
&feature
)
91 static bool initialized
= false;
92 static HashSet
<String
, CaseFoldingHash
> svgFeatures
;
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");
103 #if ENABLE(SVG_ANIMATION)
104 addString(svgFeatures
, "SVG-animation");
105 addString(svgFeatures
, "SVGDOM-animation");
107 // addString(svgFeatures, "SVG-dynamic);
108 // addString(svgFeatures, "SVGDOM-dynamic);
109 addString(svgFeatures
, "CoreAttribute");
111 addString(svgFeatures
, "Structure");
112 addString(svgFeatures
, "BasicStructure");
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");
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");
150 #if ENABLE(SVG_FONTS)
151 addString(svgFeatures
, "Font");
152 addString(svgFeatures
, "BasicFont");
154 #if ENABLE(SVG_FOREIGN_OBJECT)
155 addString(svgFeatures
, "Extensibility");
159 return svgFeatures
.contains(feature
);
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";
171 || lower
== "htmlevents"
172 || lower
== "mouseevents"
173 || lower
== "mutationevents"
175 || lower
== "stylesheets"
176 || lower
== "traversal"
177 || lower
== "uievents"
179 return version
.isEmpty() || version
== "2.0";
180 if (lower
== "xpath" || lower
== "textevents")
181 return version
.isEmpty() || version
== "3.0";
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)))
189 if ((version
.isEmpty() || version
== "1.0") && feature
.startsWith("org.w3c.", false)) {
190 if (isSVG10Feature(feature
.right(feature
.length() - 8)))
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
))
205 return DocumentType::create(0, qualifiedName
, publicId
, systemId
);
208 DOMImplementation
* DOMImplementation::getInterface(const String
& /*feature*/)
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
;
224 if (namespaceURI
== SVGNames::svgNamespaceURI
)
225 doc
= SVGDocument::create(0);
228 if (namespaceURI
== HTMLNames::xhtmlNamespaceURI
)
229 doc
= Document::createXHTML(0);
231 doc
= Document::create(0);
233 // now get the interesting parts of the doctype
235 doc
->addChild(doctype
);
237 if (!qualifiedName
.isEmpty()) {
238 doc
->addChild(doc
->createElementNS(namespaceURI
, qualifiedName
, ec
));
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
;
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")
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"))
291 PassRefPtr
<HTMLDocument
> DOMImplementation::createHTMLDocument(const String
& title
)
293 RefPtr
<HTMLDocument
> d
= HTMLDocument::create(0);
295 d
->write("<!doctype html><html><head><title>" + title
+ "</title></head><body></body></html>");
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
);
313 // Plugins cannot take FTP from us either
314 if (type
== "application/x-ftp-directory")
315 return FTPDirectoryDocument::create(frame
);
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
);
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
);
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
);
344 if (type
== "image/svg+xml") {
345 #if ENABLE(DASHBOARD_SUPPORT)
346 Settings
* settings
= frame
? frame
->settings() : 0;
347 if (!settings
|| !settings
->usesDashboardBackwardCompatibilityMode())
349 return SVGDocument::create(frame
);
352 if (isXMLMIMEType(type
))
353 return Document::create(frame
);
355 return HTMLDocument::create(frame
);