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)
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include "core/dom/DOMImplementation.h"
28 #include "bindings/core/v8/ExceptionState.h"
29 #include "core/HTMLNames.h"
30 #include "core/SVGNames.h"
31 #include "core/css/CSSStyleSheet.h"
32 #include "core/css/MediaList.h"
33 #include "core/css/StyleSheetContents.h"
34 #include "core/dom/ContextFeatures.h"
35 #include "core/dom/DocumentInit.h"
36 #include "core/dom/DocumentType.h"
37 #include "core/dom/Element.h"
38 #include "core/dom/ExceptionCode.h"
39 #include "core/dom/Text.h"
40 #include "core/dom/XMLDocument.h"
41 #include "core/dom/custom/CustomElementRegistrationContext.h"
42 #include "core/frame/LocalFrame.h"
43 #include "core/frame/UseCounter.h"
44 #include "core/html/HTMLDocument.h"
45 #include "core/html/HTMLHeadElement.h"
46 #include "core/html/HTMLMediaElement.h"
47 #include "core/html/HTMLTitleElement.h"
48 #include "core/html/HTMLViewSourceDocument.h"
49 #include "core/html/ImageDocument.h"
50 #include "core/html/MediaDocument.h"
51 #include "core/html/PluginDocument.h"
52 #include "core/html/TextDocument.h"
53 #include "core/loader/FrameLoader.h"
54 #include "core/page/Page.h"
55 #include "platform/ContentType.h"
56 #include "platform/MIMETypeRegistry.h"
57 #include "platform/graphics/Image.h"
58 #include "platform/plugins/PluginData.h"
59 #include "platform/weborigin/SecurityOrigin.h"
60 #include "wtf/StdLibExtras.h"
64 DOMImplementation::DOMImplementation(Document
& document
)
65 : m_document(document
)
69 PassRefPtrWillBeRawPtr
<DocumentType
> DOMImplementation::createDocumentType(const AtomicString
& qualifiedName
,
70 const String
& publicId
, const String
& systemId
, ExceptionState
& exceptionState
)
72 AtomicString prefix
, localName
;
73 if (!Document::parseQualifiedName(qualifiedName
, prefix
, localName
, exceptionState
))
76 return DocumentType::create(m_document
, qualifiedName
, publicId
, systemId
);
79 PassRefPtrWillBeRawPtr
<XMLDocument
> DOMImplementation::createDocument(const AtomicString
& namespaceURI
,
80 const AtomicString
& qualifiedName
, DocumentType
* doctype
, ExceptionState
& exceptionState
)
82 RefPtrWillBeRawPtr
<XMLDocument
> doc
= nullptr;
83 DocumentInit init
= DocumentInit::fromContext(document().contextDocument());
84 if (namespaceURI
== SVGNames::svgNamespaceURI
) {
85 doc
= XMLDocument::createSVG(init
);
86 } else if (namespaceURI
== HTMLNames::xhtmlNamespaceURI
) {
87 doc
= XMLDocument::createXHTML(init
.withRegistrationContext(document().registrationContext()));
89 doc
= XMLDocument::create(init
);
92 doc
->setSecurityOrigin(document().securityOrigin()->isolatedCopy());
93 doc
->setContextFeatures(document().contextFeatures());
95 RefPtrWillBeRawPtr
<Node
> documentElement
= nullptr;
96 if (!qualifiedName
.isEmpty()) {
97 documentElement
= doc
->createElementNS(namespaceURI
, qualifiedName
, exceptionState
);
98 if (exceptionState
.hadException())
103 doc
->appendChild(doctype
);
105 doc
->appendChild(documentElement
.release());
107 return doc
.release();
110 bool DOMImplementation::isXMLMIMEType(const String
& mimeType
)
112 if (equalIgnoringCase(mimeType
, "text/xml")
113 || equalIgnoringCase(mimeType
, "application/xml")
114 || equalIgnoringCase(mimeType
, "text/xsl"))
117 // Per RFCs 3023 and 2045, an XML MIME type is of the form:
118 // ^[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+/[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]+\+xml$
120 int length
= mimeType
.length();
124 if (mimeType
[0] == '/' || mimeType
[length
- 5] == '/' || !mimeType
.endsWith("+xml", TextCaseInsensitive
))
127 bool hasSlash
= false;
128 for (int i
= 0; i
< length
- 4; ++i
) {
129 UChar ch
= mimeType
[i
];
130 if (ch
>= '0' && ch
<= '9')
132 if (ch
>= 'a' && ch
<= 'z')
134 if (ch
>= 'A' && ch
<= 'Z')
168 bool DOMImplementation::isJSONMIMEType(const String
& mimeType
)
170 if (mimeType
.startsWith("application/json", TextCaseInsensitive
))
172 if (mimeType
.startsWith("application/", TextCaseInsensitive
)) {
173 size_t subtype
= mimeType
.find("+json", 12, TextCaseInsensitive
);
174 if (subtype
!= kNotFound
) {
175 // Just check that a parameter wasn't matched.
176 size_t parameterMarker
= mimeType
.find(";");
177 if (parameterMarker
== kNotFound
) {
178 unsigned endSubtype
= static_cast<unsigned>(subtype
) + 5;
179 return endSubtype
== mimeType
.length() || isASCIISpace(mimeType
[endSubtype
]);
181 return parameterMarker
> subtype
;
187 static bool isTextPlainType(const String
& mimeType
)
189 return mimeType
.startsWith("text/", TextCaseInsensitive
)
190 && !(equalIgnoringCase(mimeType
, "text/html")
191 || equalIgnoringCase(mimeType
, "text/xml")
192 || equalIgnoringCase(mimeType
, "text/xsl"));
195 bool DOMImplementation::isTextMIMEType(const String
& mimeType
)
197 return MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType
) || isJSONMIMEType(mimeType
) || isTextPlainType(mimeType
);
200 PassRefPtrWillBeRawPtr
<HTMLDocument
> DOMImplementation::createHTMLDocument(const String
& title
)
202 DocumentInit init
= DocumentInit::fromContext(document().contextDocument())
203 .withRegistrationContext(document().registrationContext());
204 RefPtrWillBeRawPtr
<HTMLDocument
> d
= HTMLDocument::create(init
);
206 d
->write("<!doctype html><html><head></head><body></body></html>");
207 if (!title
.isNull()) {
208 HTMLHeadElement
* headElement
= d
->head();
210 RefPtrWillBeRawPtr
<HTMLTitleElement
> titleElement
= HTMLTitleElement::create(*d
);
211 headElement
->appendChild(titleElement
);
212 titleElement
->appendChild(d
->createTextNode(title
), ASSERT_NO_EXCEPTION
);
214 d
->setSecurityOrigin(document().securityOrigin()->isolatedCopy());
215 d
->setContextFeatures(document().contextFeatures());
219 PassRefPtrWillBeRawPtr
<Document
> DOMImplementation::createDocument(const String
& type
, const DocumentInit
& init
, bool inViewSourceMode
)
221 if (inViewSourceMode
)
222 return HTMLViewSourceDocument::create(init
, type
);
224 // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those.
225 if (type
== "text/html")
226 return HTMLDocument::create(init
);
227 if (type
== "application/xhtml+xml")
228 return XMLDocument::createXHTML(init
);
230 PluginData
* pluginData
= 0;
231 if (init
.frame() && init
.frame()->page() && init
.frame()->loader().allowPlugins(NotAboutToInstantiatePlugin
))
232 pluginData
= init
.frame()->page()->pluginData();
234 // PDF is one image type for which a plugin can override built-in support.
235 // We do not want QuickTime to take over all image types, obviously.
236 if ((type
== "application/pdf" || type
== "text/pdf") && pluginData
&& pluginData
->supportsMimeType(type
))
237 return PluginDocument::create(init
);
238 if (Image::supportsType(type
))
239 return ImageDocument::create(init
);
241 // Check to see if the type can be played by our media player, if so create a MediaDocument
242 if (HTMLMediaElement::supportsType(ContentType(type
)))
243 return MediaDocument::create(init
);
245 // Everything else except text/plain can be overridden by plugins. In particular, Adobe SVG Viewer should be used for SVG, if installed.
246 // Disallowing plugins to use text/plain prevents plugins from hijacking a fundamental type that the browser is expected to handle,
247 // and also serves as an optimization to prevent loading the plugin database in the common case.
248 if (type
!= "text/plain" && pluginData
&& pluginData
->supportsMimeType(type
))
249 return PluginDocument::create(init
);
250 if (isTextMIMEType(type
))
251 return TextDocument::create(init
);
252 if (type
== "image/svg+xml")
253 return XMLDocument::createSVG(init
);
254 if (isXMLMIMEType(type
))
255 return XMLDocument::create(init
);
257 return HTMLDocument::create(init
);
260 DEFINE_TRACE(DOMImplementation
)
262 visitor
->trace(m_document
);