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