WebCore/dom/DOMImplementation.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     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)
       
     7  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
       
     8  *
       
     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.
       
    13  *
       
    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.
       
    18  *
       
    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.
       
    23  */
       
    24 
       
    25 #include "config.h"
       
    26 #include "DOMImplementation.h"
       
    27 
       
    28 #include "ContentType.h"
       
    29 #include "CSSStyleSheet.h"
       
    30 #include "DocumentType.h"
       
    31 #include "Element.h"
       
    32 #include "ExceptionCode.h"
       
    33 #include "Frame.h"
       
    34 #include "FrameLoaderClient.h"
       
    35 #include "FTPDirectoryDocument.h"
       
    36 #include "HTMLDocument.h"
       
    37 #include "HTMLNames.h"
       
    38 #include "HTMLViewSourceDocument.h"
       
    39 #include "Image.h"
       
    40 #include "ImageDocument.h"
       
    41 #include "MediaDocument.h"
       
    42 #include "MediaList.h"
       
    43 #include "MediaPlayer.h"
       
    44 #include "MIMETypeRegistry.h"
       
    45 #include "Page.h"
       
    46 #include "PluginData.h"
       
    47 #include "PluginDocument.h"
       
    48 #include "RegularExpression.h"
       
    49 #include "Settings.h"
       
    50 #include "TextDocument.h"
       
    51 #include "XMLNames.h"
       
    52 #include <wtf/StdLibExtras.h>
       
    53 
       
    54 #if ENABLE(SVG)
       
    55 #include "SVGNames.h"
       
    56 #include "SVGDocument.h"
       
    57 #endif
       
    58 
       
    59 #if ENABLE(WML)
       
    60 #include "WMLNames.h"
       
    61 #include "WMLDocument.h"
       
    62 #endif
       
    63 
       
    64 namespace WebCore {
       
    65 
       
    66 #if ENABLE(SVG)
       
    67 
       
    68 typedef HashSet<String, CaseFoldingHash> FeatureSet;
       
    69 
       
    70 static void addString(FeatureSet& set, const char* string)
       
    71 {
       
    72     set.add(string);
       
    73 }
       
    74 
       
    75 static bool isSVG10Feature(const String &feature)
       
    76 {
       
    77     static bool initialized = false;
       
    78     DEFINE_STATIC_LOCAL(FeatureSet, svgFeatures, ());
       
    79     if (!initialized) {
       
    80 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(FILTERS) && ENABLE(SVG_FONTS)
       
    81         addString(svgFeatures, "svg");
       
    82         addString(svgFeatures, "svg.static");
       
    83 #endif
       
    84 //      addString(svgFeatures, "svg.animation");
       
    85 //      addString(svgFeatures, "svg.dynamic");
       
    86 //      addString(svgFeatures, "svg.dom.animation");
       
    87 //      addString(svgFeatures, "svg.dom.dynamic");
       
    88 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(FILTERS) && ENABLE(SVG_FONTS)
       
    89         addString(svgFeatures, "dom");
       
    90         addString(svgFeatures, "dom.svg");
       
    91         addString(svgFeatures, "dom.svg.static");
       
    92 #endif
       
    93 //      addString(svgFeatures, "svg.all");
       
    94 //      addString(svgFeatures, "dom.svg.all");
       
    95         initialized = true;
       
    96     }
       
    97     return svgFeatures.contains(feature);
       
    98 }
       
    99 
       
   100 static bool isSVG11Feature(const String &feature)
       
   101 {
       
   102     static bool initialized = false;
       
   103     DEFINE_STATIC_LOCAL(FeatureSet, svgFeatures, ());
       
   104     if (!initialized) {
       
   105         // Sadly, we cannot claim to implement any of the SVG 1.1 generic feature sets
       
   106         // lack of Font and Filter support.
       
   107         // http://bugs.webkit.org/show_bug.cgi?id=15480
       
   108 #if ENABLE(SVG_USE) && ENABLE(SVG_FOREIGN_OBJECT) && ENABLE(FILTERS) && ENABLE(SVG_FONTS)
       
   109         addString(svgFeatures, "SVG");
       
   110         addString(svgFeatures, "SVGDOM");
       
   111         addString(svgFeatures, "SVG-static");
       
   112         addString(svgFeatures, "SVGDOM-static");
       
   113 #endif
       
   114 #if ENABLE(SVG_ANIMATION)
       
   115         addString(svgFeatures, "SVG-animation");
       
   116         addString(svgFeatures, "SVGDOM-animation");
       
   117 #endif
       
   118 //      addString(svgFeatures, "SVG-dynamic);
       
   119 //      addString(svgFeatures, "SVGDOM-dynamic);
       
   120         addString(svgFeatures, "CoreAttribute");
       
   121 #if ENABLE(SVG_USE)
       
   122         addString(svgFeatures, "Structure");
       
   123         addString(svgFeatures, "BasicStructure");
       
   124 #endif
       
   125         addString(svgFeatures, "ContainerAttribute");
       
   126         addString(svgFeatures, "ConditionalProcessing");
       
   127         addString(svgFeatures, "Image");
       
   128         addString(svgFeatures, "Style");
       
   129         addString(svgFeatures, "ViewportAttribute");
       
   130         addString(svgFeatures, "Shape");
       
   131 //      addString(svgFeatures, "Text"); // requires altGlyph, bug 6426
       
   132         addString(svgFeatures, "BasicText");
       
   133         addString(svgFeatures, "PaintAttribute");
       
   134         addString(svgFeatures, "BasicPaintAttribute");
       
   135         addString(svgFeatures, "OpacityAttribute");
       
   136         addString(svgFeatures, "GraphicsAttribute");
       
   137         addString(svgFeatures, "BaseGraphicsAttribute");
       
   138         addString(svgFeatures, "Marker");
       
   139 //      addString(svgFeatures, "ColorProfile"); // requires color-profile, bug 6037
       
   140         addString(svgFeatures, "Gradient");
       
   141         addString(svgFeatures, "Pattern");
       
   142         addString(svgFeatures, "Clip");
       
   143         addString(svgFeatures, "BasicClip");
       
   144         addString(svgFeatures, "Mask");
       
   145 #if ENABLE(FILTERS)
       
   146 //      addString(svgFeatures, "Filter");
       
   147         addString(svgFeatures, "BasicFilter");
       
   148 #endif
       
   149         addString(svgFeatures, "DocumentEventsAttribute");
       
   150         addString(svgFeatures, "GraphicalEventsAttribute");
       
   151 //      addString(svgFeatures, "AnimationEventsAttribute");
       
   152         addString(svgFeatures, "Cursor");
       
   153         addString(svgFeatures, "Hyperlinking");
       
   154         addString(svgFeatures, "XlinkAttribute");
       
   155         addString(svgFeatures, "ExternalResourcesRequired");
       
   156 //      addString(svgFeatures, "View"); // buggy <view> support, bug 16962
       
   157         addString(svgFeatures, "Script");
       
   158 #if ENABLE(SVG_ANIMATION)
       
   159         addString(svgFeatures, "Animation"); 
       
   160 #endif
       
   161 #if ENABLE(SVG_FONTS)
       
   162         addString(svgFeatures, "Font");
       
   163         addString(svgFeatures, "BasicFont");
       
   164 #endif
       
   165 #if ENABLE(SVG_FOREIGN_OBJECT)
       
   166         addString(svgFeatures, "Extensibility");
       
   167 #endif
       
   168         initialized = true;
       
   169     }
       
   170     return svgFeatures.contains(feature);
       
   171 }
       
   172 #endif
       
   173 
       
   174 bool DOMImplementation::hasFeature(const String& feature, const String& version)
       
   175 {
       
   176     String lower = feature.lower();
       
   177     if (lower == "core" || lower == "html" || lower == "xml" || lower == "xhtml")
       
   178         return version.isEmpty() || version == "1.0" || version == "2.0";
       
   179     if (lower == "css"
       
   180             || lower == "css2"
       
   181             || lower == "events"
       
   182             || lower == "htmlevents"
       
   183             || lower == "mouseevents"
       
   184             || lower == "mutationevents"
       
   185             || lower == "range"
       
   186             || lower == "stylesheets"
       
   187             || lower == "traversal"
       
   188             || lower == "uievents"
       
   189             || lower == "views")
       
   190         return version.isEmpty() || version == "2.0";
       
   191     if (lower == "xpath" || lower == "textevents")
       
   192         return version.isEmpty() || version == "3.0";
       
   193 
       
   194 #if ENABLE(SVG)
       
   195     if ((version.isEmpty() || version == "1.1") && feature.startsWith("http://www.w3.org/tr/svg11/feature#", false)) {
       
   196         if (isSVG11Feature(feature.right(feature.length() - 35)))
       
   197             return true;
       
   198     }
       
   199 
       
   200     if ((version.isEmpty() || version == "1.0") && feature.startsWith("org.w3c.", false)) {
       
   201         if (isSVG10Feature(feature.right(feature.length() - 8)))
       
   202             return true;
       
   203     }
       
   204 #endif
       
   205     
       
   206     return false;
       
   207 }
       
   208 
       
   209 PassRefPtr<DocumentType> DOMImplementation::createDocumentType(const String& qualifiedName,
       
   210     const String& publicId, const String& systemId, ExceptionCode& ec)
       
   211 {
       
   212     String prefix, localName;
       
   213     if (!Document::parseQualifiedName(qualifiedName, prefix, localName, ec))
       
   214         return 0;
       
   215 
       
   216     return DocumentType::create(0, qualifiedName, publicId, systemId);
       
   217 }
       
   218 
       
   219 DOMImplementation* DOMImplementation::getInterface(const String& /*feature*/)
       
   220 {
       
   221     return 0;
       
   222 }
       
   223 
       
   224 PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceURI,
       
   225     const String& qualifiedName, DocumentType* doctype, ExceptionCode& ec)
       
   226 {
       
   227     RefPtr<Document> doc;
       
   228 #if ENABLE(SVG)
       
   229     if (namespaceURI == SVGNames::svgNamespaceURI)
       
   230         doc = SVGDocument::create(0, KURL());
       
   231     else
       
   232 #endif
       
   233 #if ENABLE(WML)
       
   234     if (namespaceURI == WMLNames::wmlNamespaceURI)
       
   235         doc = WMLDocument::create(0, KURL());
       
   236     else
       
   237 #endif
       
   238     if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
       
   239         doc = Document::createXHTML(0, KURL());
       
   240     else
       
   241         doc = Document::create(0, KURL());
       
   242 
       
   243     RefPtr<Node> documentElement;
       
   244     if (!qualifiedName.isEmpty()) {
       
   245         documentElement = doc->createElementNS(namespaceURI, qualifiedName, ec);
       
   246         if (ec)
       
   247             return 0;
       
   248     }
       
   249 
       
   250     // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
       
   251     // created from a different implementation.
       
   252     // Hixie's interpretation of the DOM Core spec suggests we should prefer
       
   253     // other exceptions to WRONG_DOCUMENT_ERR (based on order mentioned in spec).
       
   254     if (doctype && doctype->document()) {
       
   255         ec = WRONG_DOCUMENT_ERR;
       
   256         return 0;
       
   257     }
       
   258 
       
   259     // FIXME: Shouldn't this call appendChild instead?
       
   260     if (doctype)
       
   261         doc->legacyParserAddChild(doctype);
       
   262     if (documentElement)
       
   263         doc->legacyParserAddChild(documentElement.release());
       
   264 
       
   265     return doc.release();
       
   266 }
       
   267 
       
   268 PassRefPtr<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&, const String& media, ExceptionCode&)
       
   269 {
       
   270     // FIXME: Title should be set.
       
   271     // FIXME: Media could have wrong syntax, in which case we should generate an exception.
       
   272     RefPtr<CSSStyleSheet> sheet = CSSStyleSheet::create();
       
   273     sheet->setMedia(MediaList::createAllowingDescriptionSyntax(sheet.get(), media));
       
   274     return sheet.release();
       
   275 }
       
   276 
       
   277 bool DOMImplementation::isXMLMIMEType(const String& mimeType)
       
   278 {
       
   279     if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
       
   280         return true;
       
   281     static const char* const validChars = "[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]"; // per RFCs: 3023, 2045
       
   282     DEFINE_STATIC_LOCAL(RegularExpression, xmlTypeRegExp, (String("^") + validChars + "+/" + validChars + "+\\+xml$", TextCaseSensitive));
       
   283     return xmlTypeRegExp.match(mimeType) > -1;
       
   284 }
       
   285 
       
   286 bool DOMImplementation::isTextMIMEType(const String& mimeType)
       
   287 {
       
   288     if (MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType)
       
   289         || mimeType == "application/json" // Render JSON as text/plain.
       
   290         || (mimeType.startsWith("text/") && mimeType != "text/html"
       
   291             && mimeType != "text/xml" && mimeType != "text/xsl"))
       
   292         return true;
       
   293 
       
   294     return false;
       
   295 }
       
   296 
       
   297 PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& title)
       
   298 {
       
   299     RefPtr<HTMLDocument> d = HTMLDocument::create(0, KURL());
       
   300     d->open();
       
   301     d->write("<!doctype html><html><body></body></html>");
       
   302     d->setTitle(title);
       
   303     return d.release();
       
   304 }
       
   305 
       
   306 PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, const KURL& url, bool inViewSourceMode)
       
   307 {
       
   308     if (inViewSourceMode)
       
   309         return HTMLViewSourceDocument::create(frame, url, type);
       
   310 
       
   311     // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those.
       
   312     if (type == "text/html")
       
   313         return HTMLDocument::create(frame, url);
       
   314     if (type == "application/xhtml+xml"
       
   315 #if ENABLE(XHTMLMP)
       
   316         || type == "application/vnd.wap.xhtml+xml"
       
   317 #endif
       
   318         )
       
   319         return Document::createXHTML(frame, url);
       
   320 
       
   321 #if ENABLE(WML)
       
   322     if (type == "text/vnd.wap.wml" || type == "application/vnd.wap.wmlc")
       
   323         return WMLDocument::create(frame, url);
       
   324 #endif
       
   325 
       
   326 #if ENABLE(FTPDIR)
       
   327     // Plugins cannot take FTP from us either
       
   328     if (type == "application/x-ftp-directory")
       
   329         return FTPDirectoryDocument::create(frame, url);
       
   330 #endif
       
   331 
       
   332     PluginData* pluginData = 0;
       
   333     if (frame && frame->page() && frame->loader()->subframeLoader()->allowPlugins(NotAboutToInstantiatePlugin))
       
   334         pluginData = frame->page()->pluginData();
       
   335 
       
   336     // PDF is one image type for which a plugin can override built-in support.
       
   337     // We do not want QuickTime to take over all image types, obviously.
       
   338     if ((type == "application/pdf" || type == "text/pdf") && pluginData && pluginData->supportsMimeType(type))
       
   339         return PluginDocument::create(frame, url);
       
   340     if (Image::supportsType(type))
       
   341         return ImageDocument::create(frame, url);
       
   342 
       
   343 #if ENABLE(VIDEO)
       
   344      // Check to see if the type can be played by our MediaPlayer, if so create a MediaDocument
       
   345      if (MediaPlayer::supportsType(ContentType(type)))
       
   346          return MediaDocument::create(frame, url);
       
   347 #endif
       
   348 
       
   349     // Everything else except text/plain can be overridden by plugins. In particular, Adobe SVG Viewer should be used for SVG, if installed.
       
   350     // Disallowing plug-ins to use text/plain prevents plug-ins from hijacking a fundamental type that the browser is expected to handle,
       
   351     // and also serves as an optimization to prevent loading the plug-in database in the common case.
       
   352     if (type != "text/plain" && pluginData && pluginData->supportsMimeType(type)) 
       
   353         return PluginDocument::create(frame, url);
       
   354     if (isTextMIMEType(type))
       
   355         return TextDocument::create(frame, url);
       
   356 
       
   357 #if ENABLE(SVG)
       
   358     if (type == "image/svg+xml") {
       
   359 #if ENABLE(DASHBOARD_SUPPORT)    
       
   360         Settings* settings = frame ? frame->settings() : 0;
       
   361         if (!settings || !settings->usesDashboardBackwardCompatibilityMode())
       
   362 #endif
       
   363             return SVGDocument::create(frame, url);
       
   364     }
       
   365 #endif
       
   366     if (isXMLMIMEType(type))
       
   367         return Document::create(frame, url);
       
   368 
       
   369     return HTMLDocument::create(frame, url);
       
   370 }
       
   371 
       
   372 }