webengine/osswebengine/WebCore/dom/DOMImplementation.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /**
       
     2  * This file is part of the DOM implementation for KDE.
       
     3  *
       
     4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
       
     5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
       
     6  *           (C) 2001 Dirk Mueller (mueller@kde.org)
       
     7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
       
     8  * Copyright (C) 2006 Samuel Weinig (sam@webkit.org)
       
     9  *
       
    10  * This library is free software; you can redistribute it and/or
       
    11  * modify it under the terms of the GNU Library General Public
       
    12  * License as published by the Free Software Foundation; either
       
    13  * version 2 of the License, or (at your option) any later version.
       
    14  *
       
    15  * This library is distributed in the hope that it will be useful,
       
    16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    18  * Library General Public License for more details.
       
    19  *
       
    20  * You should have received a copy of the GNU Library General Public License
       
    21  * along with this library; see the file COPYING.LIB.  If not, write to
       
    22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       
    23  * Boston, MA 02110-1301, USA.
       
    24  */
       
    25 
       
    26 #include "config.h"
       
    27 #include "DOMImplementation.h"
       
    28 
       
    29 #include "CSSStyleSheet.h"
       
    30 #include "DocumentType.h"
       
    31 #include "Element.h"
       
    32 #include "ExceptionCode.h"
       
    33 #include "Frame.h"
       
    34 #include "FTPDirectoryDocument.h"
       
    35 #include "HTMLDocument.h"
       
    36 #include "HTMLNames.h"
       
    37 #include "HTMLViewSourceDocument.h"
       
    38 #include "Image.h"
       
    39 #include "ImageDocument.h"
       
    40 #include "MediaList.h"
       
    41 #include "Page.h"
       
    42 #include "PluginDocument.h"
       
    43 #include "PlugInInfoStore.h"
       
    44 #include "RegularExpression.h"
       
    45 #include "Settings.h"
       
    46 #include "TextDocument.h"
       
    47 #include "XMLNames.h"
       
    48 
       
    49 #if ENABLE(SVG)
       
    50 #include "SVGNames.h"
       
    51 #include "SVGDocument.h"
       
    52 #endif
       
    53 
       
    54 namespace WebCore {
       
    55 
       
    56 // FIXME: An implementation of this is still waiting for me to understand the distinction between
       
    57 // a "malformed" qualified name and one with bad characters in it. For example, is a second colon
       
    58 // an illegal character or a malformed qualified name? This will determine both what parameters
       
    59 // this function needs to take and exactly what it will do. Should also be exported so that
       
    60 // Element can use it too.
       
    61 static bool qualifiedNameIsMalformed(const String&)
       
    62 {
       
    63     return false;
       
    64 }
       
    65 
       
    66 #if ENABLE(SVG)
       
    67 
       
    68 static void addString(HashSet<StringImpl*, CaseInsensitiveHash<StringImpl*> >& set, const
       
    69 char* string)
       
    70 {
       
    71     StringImpl* s = new StringImpl(string);
       
    72     s->ref();
       
    73     set.add(s);
       
    74 }
       
    75 
       
    76 static bool isSVG10Feature(const String &feature)
       
    77 {
       
    78     static bool initialized = false;
       
    79     static HashSet<StringImpl*, CaseInsensitiveHash<StringImpl*> > svgFeatures;
       
    80     if (!initialized) {
       
    81         // TODO: features need to be uncommented when we implement them
       
    82         // 1.0 features
       
    83         addString(svgFeatures, "svg");
       
    84         addString(svgFeatures, "svg.static");
       
    85 //      addString(svgFeatures, "svg.animation");
       
    86 //      addString(svgFeatures, "svg.dynamic");
       
    87 //      addString(svgFeatures, "svg.dom.animation");
       
    88 //      addString(svgFeatures, "svg.dom.dynamic");
       
    89         addString(svgFeatures, "dom");
       
    90         addString(svgFeatures, "dom.svg");
       
    91         addString(svgFeatures, "dom.svg.static");
       
    92 //      addString(svgFeatures, "svg.all");
       
    93 //      addString(svgFeatures, "dom.svg.all");
       
    94         initialized = true;
       
    95     }
       
    96     return svgFeatures.contains(feature.impl());
       
    97 }
       
    98 
       
    99 static bool isSVG11Feature(const String &feature)
       
   100 {
       
   101     static bool initialized = false;
       
   102     static HashSet<StringImpl*, CaseInsensitiveHash<StringImpl*> > svgFeatures;
       
   103     if (!initialized) {
       
   104         // TODO: features need to be uncommented when we implement them
       
   105         // 1.1 features
       
   106         addString(svgFeatures, "SVG");
       
   107         addString(svgFeatures, "SVGDOM");
       
   108         addString(svgFeatures, "SVG-static");
       
   109         addString(svgFeatures, "SVGDOM-static");
       
   110 //      addString(svgFeatures, "SVG-animation);
       
   111 //      addString(svgFeatures, "SVGDOM-animation);
       
   112 //      addString(svgFeatures, "SVG-dynamic);
       
   113 //      addString(svgFeatures, "SVGDOM-dynamic);
       
   114         addString(svgFeatures, "CoreAttribute");
       
   115         addString(svgFeatures, "Structure");
       
   116         addString(svgFeatures, "BasicStructure");
       
   117         addString(svgFeatures, "ContainerAttribute");
       
   118         addString(svgFeatures, "ConditionalProcessing");
       
   119         addString(svgFeatures, "Image");
       
   120         addString(svgFeatures, "Style");
       
   121         addString(svgFeatures, "ViewportAttribute");
       
   122         addString(svgFeatures, "Shape");
       
   123 //      addString(svgFeatures, "Text");
       
   124 //      addString(svgFeatures, "BasicText");
       
   125         addString(svgFeatures, "PaintAttribute");
       
   126         addString(svgFeatures, "BasicPaintAttribute");
       
   127         addString(svgFeatures, "OpacityAttribute");
       
   128         addString(svgFeatures, "GraphicsAttribute");
       
   129         addString(svgFeatures, "BaseGraphicsAttribute");
       
   130         addString(svgFeatures, "Marker");
       
   131 //      addString(svgFeatures, "ColorProfile");
       
   132         addString(svgFeatures, "Gradient");
       
   133         addString(svgFeatures, "Pattern");
       
   134         addString(svgFeatures, "Clip");
       
   135         addString(svgFeatures, "BasicClip");
       
   136         addString(svgFeatures, "Mask");
       
   137 //      addString(svgFeatures, "Filter");
       
   138 //      addString(svgFeatures, "BasicFilter");
       
   139         addString(svgFeatures, "DocumentEventsAttribute");
       
   140         addString(svgFeatures, "GraphicalEventsAttribute");
       
   141         addString(svgFeatures, "AnimationEventsAttribute");
       
   142 //      addString(svgFeatures, "Cursor");
       
   143         addString(svgFeatures, "Hyperlinking");
       
   144         addString(svgFeatures, "XlinkAttribute");
       
   145 //      addString(svgFeatures, "ExternalResourcesRequired");
       
   146 //      addString(svgFeatures, "View");
       
   147         addString(svgFeatures, "Script");
       
   148 //      addString(svgFeatures, "Animation");
       
   149 //      addString(svgFeatures, "Font");
       
   150 //      addString(svgFeatures, "BasicFont");
       
   151         addString(svgFeatures, "Extensibility");
       
   152         initialized = true;
       
   153     }
       
   154     return svgFeatures.contains(feature.impl());
       
   155 }
       
   156 #endif
       
   157 
       
   158 DOMImplementation::~DOMImplementation()
       
   159 {
       
   160 }
       
   161 
       
   162 bool DOMImplementation::hasFeature (const String& feature, const String& version) const
       
   163 {
       
   164     String lower = feature.lower();
       
   165     if (lower == "core" || lower == "html" || lower == "xml" || lower == "xhtml")
       
   166         return version.isEmpty() || version == "1.0" || version == "2.0";
       
   167     if (lower == "css"
       
   168             || lower == "css2"
       
   169             || lower == "events"
       
   170             || lower == "htmlevents"
       
   171             || lower == "mouseevents"
       
   172             || lower == "mutationevents"
       
   173             || lower == "range"
       
   174             || lower == "stylesheets"
       
   175             || lower == "traversal"
       
   176             || lower == "uievents"
       
   177             || lower == "views")
       
   178         return version.isEmpty() || version == "2.0";
       
   179     if (lower == "xpath" || lower == "textevents")
       
   180         return version.isEmpty() || version == "3.0";
       
   181 
       
   182 #if ENABLE(SVG)
       
   183     if ((version.isEmpty() || version == "1.1") && feature.startsWith("http://www.w3.org/tr/svg11/feature#", false)) {
       
   184         if (isSVG11Feature(feature.right(feature.length() - 35)))
       
   185             return true;
       
   186     }
       
   187 
       
   188     if ((version.isEmpty() || version == "1.0") && feature.startsWith("org.w3c.", false)) {
       
   189         if (isSVG10Feature(feature.right(feature.length() - 8)))
       
   190             return true;
       
   191     }
       
   192 #endif
       
   193     
       
   194     return false;
       
   195 }
       
   196 
       
   197 PassRefPtr<DocumentType> DOMImplementation::createDocumentType(const String& qualifiedName,
       
   198     const String& publicId, const String& systemId, ExceptionCode& ec)
       
   199 {
       
   200     // Not mentioned in spec: throw NAMESPACE_ERR if no qualifiedName supplied
       
   201     if (qualifiedName.isNull()) {
       
   202         ec = NAMESPACE_ERR;
       
   203         return 0;
       
   204     }
       
   205 
       
   206     // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
       
   207     String prefix, localName;
       
   208     if (!Document::parseQualifiedName(qualifiedName, prefix, localName)) {
       
   209         ec = INVALID_CHARACTER_ERR;
       
   210         return 0;
       
   211     }
       
   212 
       
   213     // NAMESPACE_ERR: Raised if the qualifiedName is malformed.
       
   214     if (qualifiedNameIsMalformed(qualifiedName)) {
       
   215         ec = NAMESPACE_ERR;
       
   216         return 0;
       
   217     }
       
   218 
       
   219     ec = 0;
       
   220     return new DocumentType(this, 0, qualifiedName, publicId, systemId);
       
   221 }
       
   222 
       
   223 DOMImplementation* DOMImplementation::getInterface(const String& /*feature*/) const
       
   224 {
       
   225     // ###
       
   226     return 0;
       
   227 }
       
   228 
       
   229 PassRefPtr<Document> DOMImplementation::createDocument(const String& namespaceURI,
       
   230     const String& qualifiedName, DocumentType* doctype, ExceptionCode& ec)
       
   231 {
       
   232     if (!qualifiedName.isEmpty()) {
       
   233         // INVALID_CHARACTER_ERR: Raised if the specified qualified name contains an illegal character.
       
   234         String prefix, localName;
       
   235         if (!Document::parseQualifiedName(qualifiedName, prefix, localName)) {
       
   236             ec = INVALID_CHARACTER_ERR;
       
   237             return 0;
       
   238         }
       
   239 
       
   240         // NAMESPACE_ERR:
       
   241         // - Raised if the qualifiedName is malformed,
       
   242         // - if the qualifiedName has a prefix and the namespaceURI is null, or
       
   243         // - if the qualifiedName has a prefix that is "xml" and the namespaceURI is different
       
   244         //   from "http://www.w3.org/XML/1998/namespace" [Namespaces].
       
   245         int colonpos = -1;
       
   246         unsigned i;
       
   247         StringImpl *qname = qualifiedName.impl();
       
   248         for (i = 0; i < qname->length() && colonpos < 0; i++) {
       
   249             if ((*qname)[i] == ':')
       
   250                 colonpos = i;
       
   251         }
       
   252     
       
   253         if (qualifiedNameIsMalformed(qualifiedName) ||
       
   254             (colonpos >= 0 && namespaceURI.isNull()) ||
       
   255             (colonpos == 3 && qualifiedName[0] == 'x' && qualifiedName[1] == 'm' && qualifiedName[2] == 'l' &&
       
   256 #if ENABLE(SVG)
       
   257              namespaceURI != SVGNames::svgNamespaceURI &&
       
   258 #endif
       
   259              namespaceURI != XMLNames::xmlNamespaceURI)) {
       
   260 
       
   261             ec = NAMESPACE_ERR;
       
   262             return 0;
       
   263         }
       
   264     }
       
   265     
       
   266     // WRONG_DOCUMENT_ERR: Raised if doctype has already been used with a different document or was
       
   267     // created from a different implementation.
       
   268     if (doctype && (doctype->document() || doctype->implementation() != this)) {
       
   269         ec = WRONG_DOCUMENT_ERR;
       
   270         return 0;
       
   271     }
       
   272 
       
   273     RefPtr<Document> doc;
       
   274 #if ENABLE(SVG)
       
   275     if (namespaceURI == SVGNames::svgNamespaceURI)
       
   276         doc = new SVGDocument(this, 0);
       
   277     else
       
   278 #endif
       
   279         if (namespaceURI == HTMLNames::xhtmlNamespaceURI)
       
   280             doc = new Document(this, 0, true);
       
   281         else
       
   282             doc = new Document(this, 0);
       
   283 
       
   284     // now get the interesting parts of the doctype
       
   285     if (doctype) {
       
   286         doc->setDocType(doctype);
       
   287         doctype->setDocument(doc.get());
       
   288     }
       
   289 
       
   290     if (!qualifiedName.isEmpty())
       
   291         doc->addChild(doc->createElementNS(namespaceURI, qualifiedName, ec));
       
   292     
       
   293     ec = 0;
       
   294     return doc.release();
       
   295 }
       
   296 
       
   297 PassRefPtr<CSSStyleSheet> DOMImplementation::createCSSStyleSheet(const String&, const String& media, ExceptionCode& ec)
       
   298 {
       
   299     // ### TODO : title should be set, and media could have wrong syntax, in which case we should generate an exception.
       
   300     ec = 0;
       
   301     CSSStyleSheet* const nullSheet = 0;
       
   302     RefPtr<CSSStyleSheet> sheet = new CSSStyleSheet(nullSheet);
       
   303     sheet->setMedia(new MediaList(sheet.get(), media, true));
       
   304     return sheet.release();
       
   305 }
       
   306 
       
   307 PassRefPtr<Document> DOMImplementation::createDocument(Frame* frame)
       
   308 {
       
   309     return new Document(this, frame);
       
   310 }
       
   311 
       
   312 PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(Frame* frame)
       
   313 {
       
   314     return new HTMLDocument(this, frame);
       
   315 }
       
   316 
       
   317 DOMImplementation* DOMImplementation::instance()
       
   318 {
       
   319     static RefPtr<DOMImplementation> i = new DOMImplementation;
       
   320     return i.get();
       
   321 }
       
   322 
       
   323 bool DOMImplementation::isXMLMIMEType(const String& mimeType)
       
   324 {
       
   325     if (mimeType == "text/xml" || mimeType == "application/xml" || mimeType == "text/xsl")
       
   326         return true;
       
   327     static const char* validChars = "[0-9a-zA-Z_\\-+~!$\\^{}|.%'`#&*]"; // per RFCs: 3023, 2045
       
   328     static RegularExpression xmlTypeRegExp(DeprecatedString("^") + validChars + "+/" + validChars + "+\\+xml$");
       
   329     if (xmlTypeRegExp.match(mimeType.deprecatedString()) > -1)
       
   330         return true;
       
   331     return false;
       
   332 }
       
   333 
       
   334 bool DOMImplementation::isTextMIMEType(const String& mimeType)
       
   335 {
       
   336     if (mimeType == "application/x-javascript" ||
       
   337         (mimeType.startsWith("text/") && mimeType != "text/html" &&
       
   338          mimeType != "text/xml" && mimeType != "text/xsl"))
       
   339         return true;
       
   340     
       
   341     return false;
       
   342 }
       
   343 
       
   344 PassRefPtr<HTMLDocument> DOMImplementation::createHTMLDocument(const String& title)
       
   345 {
       
   346     RefPtr<HTMLDocument> d = new HTMLDocument(this, 0);
       
   347     d->open();
       
   348     d->write("<html><head><title>" + title + "</title></head><body></body></html>");
       
   349     return d.release();
       
   350 }
       
   351 
       
   352 PassRefPtr<Document> DOMImplementation::createDocument(const String& type, Frame* frame, bool inViewSourceMode)
       
   353 {
       
   354     if (inViewSourceMode) {
       
   355         if (type == "text/html" || type == "application/xhtml+xml" || type == "image/svg+xml" || isTextMIMEType(type) || isXMLMIMEType(type))
       
   356             return new HTMLViewSourceDocument(this, frame, type);
       
   357     }
       
   358     
       
   359     if ( type == "text/vnd.wap.wml" || type == "text/vnd.wap.wmlc" || type == "application/vnd.wap.wmlc" || type == "application/vnd.wap.wmlscriptc") {
       
   360         return NULL;
       
   361     }
       
   362 
       
   363     // Plugins cannot take HTML and XHTML from us, and we don't even need to initialize the plugin database for those.
       
   364     if (type == "text/html")
       
   365         return new HTMLDocument(this, frame);
       
   366     if (type == "application/xhtml+xml")
       
   367 #if PLATFORM(SYMBIAN)
       
   368         return new HTMLDocument(this, frame);
       
   369     if (type == "application/vnd.wap.xhtml+xml")        
       
   370         return new HTMLDocument(this, frame);
       
   371 #else
       
   372         return new Document(this, frame, true);
       
   373 #endif     
       
   374     
       
   375 #if ENABLE(FTPDIR)
       
   376     // Plugins cannot take FTP from us either
       
   377     if (type == "application/x-ftp-directory")
       
   378         return new FTPDirectoryDocument(this, frame);
       
   379 #endif
       
   380 
       
   381     // PDF is one image type for which a plugin can override built-in support.
       
   382     // We do not want QuickTime to take over all image types, obviously.
       
   383     if ((type == "application/pdf" || type == "text/pdf") && PlugInInfoStore::supportsMIMEType(type))
       
   384         return new PluginDocument(this, frame);
       
   385     if (Image::supportsType(type))
       
   386         return new ImageDocument(this, frame);
       
   387     // Everything else except text/plain can be overridden by plugins. In particular, Adobe SVG Viewer should be used for SVG, if installed.
       
   388     // Disallowing plug-ins to use text/plain prevents plug-ins from hijacking a fundamental type that the browser is expected to handle,
       
   389     // and also serves as an optimization to prevent loading the plug-in database in the common case.
       
   390     if (type != "text/plain" && PlugInInfoStore::supportsMIMEType(type)) 
       
   391         return new PluginDocument(this, frame);
       
   392     if (isTextMIMEType(type))
       
   393         return new TextDocument(this, frame);
       
   394 
       
   395 #if ENABLE(SVG)
       
   396     if (type == "image/svg+xml") {
       
   397         Settings* settings = frame ? frame->settings() : 0;
       
   398         if (!settings || !settings->usesDashboardBackwardCompatibilityMode())
       
   399             return new SVGDocument(this, frame);
       
   400     }
       
   401 #endif
       
   402     if (isXMLMIMEType(type))
       
   403         return new Document(this, frame);
       
   404 
       
   405     
       
   406     return new HTMLDocument(this, frame);
       
   407 }
       
   408 
       
   409 }