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