Home | History | Annotate | Download | only in svg
      1 /*
      2     Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      3                   2004, 2005, 2007 Rob Buis <buis (at) kde.org>
      4 
      5     This library is free software; you can redistribute it and/or
      6     modify it under the terms of the GNU Library General Public
      7     License as published by the Free Software Foundation; either
      8     version 2 of the License, or (at your option) any later version.
      9 
     10     This library is distributed in the hope that it will be useful,
     11     but WITHOUT ANY WARRANTY; without even the implied warranty of
     12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13     Library General Public License for more details.
     14 
     15     You should have received a copy of the GNU Library General Public License
     16     along with this library; see the file COPYING.LIB.  If not, write to
     17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18     Boston, MA 02110-1301, USA.
     19 */
     20 
     21 #include "config.h"
     22 
     23 #if ENABLE(SVG)
     24 #include "SVGScriptElement.h"
     25 
     26 #include "Document.h"
     27 #include "Event.h"
     28 #include "EventNames.h"
     29 #include "MappedAttribute.h"
     30 #include "SVGNames.h"
     31 
     32 namespace WebCore {
     33 
     34 SVGScriptElement::SVGScriptElement(const QualifiedName& tagName, Document* doc, bool createdByParser)
     35     : SVGElement(tagName, doc)
     36     , SVGURIReference()
     37     , SVGExternalResourcesRequired()
     38     , m_data(this, this)
     39 {
     40     m_data.setCreatedByParser(createdByParser);
     41 }
     42 
     43 SVGScriptElement::~SVGScriptElement()
     44 {
     45 }
     46 
     47 String SVGScriptElement::scriptContent() const
     48 {
     49     return m_data.scriptContent();
     50 }
     51 
     52 void SVGScriptElement::parseMappedAttribute(MappedAttribute* attr)
     53 {
     54     const QualifiedName& attrName = attr->name();
     55 
     56     if (attrName == SVGNames::typeAttr)
     57         setType(attr->value());
     58     else {
     59         if (SVGURIReference::parseMappedAttribute(attr))
     60             return;
     61         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
     62             return;
     63 
     64         SVGElement::parseMappedAttribute(attr);
     65     }
     66 }
     67 
     68 void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
     69 {
     70     SVGElement::svgAttributeChanged(attrName);
     71 
     72     if (SVGURIReference::isKnownAttribute(attrName))
     73         handleSourceAttribute(m_data, href());
     74     else if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
     75         // Handle dynamic updates of the 'externalResourcesRequired' attribute. Only possible case: changing from 'true' to 'false'
     76         // causes an immediate dispatch of the SVGLoad event. If the attribute value was 'false' before inserting the script element
     77         // in the document, the SVGLoad event has already been dispatched.
     78         if (!externalResourcesRequiredBaseValue() && !m_data.haveFiredLoadEvent() && !m_data.createdByParser()) {
     79             m_data.setHaveFiredLoadEvent(true);
     80             ASSERT(haveLoadedRequiredResources());
     81 
     82             sendSVGLoadEventIfPossible();
     83         }
     84     }
     85 }
     86 
     87 void SVGScriptElement::synchronizeProperty(const QualifiedName& attrName)
     88 {
     89     SVGElement::synchronizeProperty(attrName);
     90 
     91     if (attrName == anyQName()) {
     92         synchronizeExternalResourcesRequired();
     93         synchronizeHref();
     94         return;
     95     }
     96 
     97     if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
     98         synchronizeExternalResourcesRequired();
     99     else if (SVGURIReference::isKnownAttribute(attrName))
    100         synchronizeHref();
    101 }
    102 
    103 void SVGScriptElement::insertedIntoDocument()
    104 {
    105     SVGElement::insertedIntoDocument();
    106     ScriptElement::insertedIntoDocument(m_data, sourceAttributeValue());
    107 
    108     if (m_data.createdByParser())
    109         return;
    110 
    111     // Eventually send SVGLoad event now for the dynamically inserted script element
    112     if (!externalResourcesRequiredBaseValue()) {
    113         m_data.setHaveFiredLoadEvent(true);
    114         sendSVGLoadEventIfPossible();
    115     }
    116 }
    117 
    118 void SVGScriptElement::removedFromDocument()
    119 {
    120     SVGElement::removedFromDocument();
    121     ScriptElement::removedFromDocument(m_data);
    122 }
    123 
    124 void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
    125 {
    126     ScriptElement::childrenChanged(m_data);
    127     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
    128 }
    129 
    130 bool SVGScriptElement::isURLAttribute(Attribute* attr) const
    131 {
    132     return attr->name() == sourceAttributeValue();
    133 }
    134 
    135 void SVGScriptElement::finishParsingChildren()
    136 {
    137     ScriptElement::finishParsingChildren(m_data, sourceAttributeValue());
    138     SVGElement::finishParsingChildren();
    139 
    140     // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
    141     if (!externalResourcesRequiredBaseValue())
    142         m_data.setHaveFiredLoadEvent(true);
    143 }
    144 
    145 String SVGScriptElement::type() const
    146 {
    147     return m_type;
    148 }
    149 
    150 void SVGScriptElement::setType(const String& type)
    151 {
    152     m_type = type;
    153 }
    154 
    155 String SVGScriptElement::scriptCharset() const
    156 {
    157     return m_data.scriptCharset();
    158 }
    159 
    160 void SVGScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
    161 {
    162     SVGElement::addSubresourceAttributeURLs(urls);
    163 
    164     addSubresourceURL(urls, document()->completeURL(href()));
    165 }
    166 
    167 bool SVGScriptElement::haveLoadedRequiredResources()
    168 {
    169     return !externalResourcesRequiredBaseValue() || m_data.haveFiredLoadEvent();
    170 }
    171 
    172 String SVGScriptElement::sourceAttributeValue() const
    173 {
    174     return href();
    175 }
    176 
    177 String SVGScriptElement::charsetAttributeValue() const
    178 {
    179     return String();
    180 }
    181 
    182 String SVGScriptElement::typeAttributeValue() const
    183 {
    184     return type();
    185 }
    186 
    187 String SVGScriptElement::languageAttributeValue() const
    188 {
    189     return String();
    190 }
    191 
    192 String SVGScriptElement::forAttributeValue() const
    193 {
    194     return String();
    195 }
    196 
    197 void SVGScriptElement::dispatchLoadEvent()
    198 {
    199     bool externalResourcesRequired = externalResourcesRequiredBaseValue();
    200 
    201     if (m_data.createdByParser())
    202         ASSERT(externalResourcesRequired != m_data.haveFiredLoadEvent());
    203     else if (m_data.haveFiredLoadEvent()) {
    204         // If we've already fired an load event and externalResourcesRequired is set to 'true'
    205         // externalResourcesRequired has been modified while loading the <script>. Don't dispatch twice.
    206         if (externalResourcesRequired)
    207             return;
    208     }
    209 
    210     // HTML and SVG differ completly in the 'onload' event handling of <script> elements.
    211     // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwhise an error event.
    212     // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
    213     // is set to 'false', otherwhise it dispatches the 'SVGLoad' event just after loading the remote resource.
    214     if (externalResourcesRequired) {
    215         ASSERT(!m_data.haveFiredLoadEvent());
    216 
    217         // Dispatch SVGLoad event
    218         m_data.setHaveFiredLoadEvent(true);
    219         ASSERT(haveLoadedRequiredResources());
    220 
    221         sendSVGLoadEventIfPossible();
    222     }
    223 }
    224 
    225 void SVGScriptElement::dispatchErrorEvent()
    226 {
    227     dispatchEvent(Event::create(eventNames().errorEvent, true, false));
    228 }
    229 
    230 }
    231 
    232 #endif // ENABLE(SVG)
    233