initial import
[vuplus_webkit] / Source / WebCore / svg / SVGScriptElement.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@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 "Attribute.h"
27 #include "Document.h"
28 #include "Event.h"
29 #include "EventNames.h"
30 #include "HTMLNames.h"
31 #include "SVGAnimatedStaticPropertyTearOff.h"
32 #include "SVGElementInstance.h"
33 #include "SVGNames.h"
34 #include "ScriptEventListener.h"
35
36 namespace WebCore {
37
38 // Animated property definitions
39 DEFINE_ANIMATED_STRING(SVGScriptElement, XLinkNames::hrefAttr, Href, href)
40 DEFINE_ANIMATED_BOOLEAN(SVGScriptElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
41
42 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGScriptElement)
43     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
44     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
45 END_REGISTER_ANIMATED_PROPERTIES
46
47 inline SVGScriptElement::SVGScriptElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser, bool alreadyStarted)
48     : SVGElement(tagName, document)
49     , ScriptElement(this, wasInsertedByParser, alreadyStarted)
50 {
51     ASSERT(hasTagName(SVGNames::scriptTag));
52     registerAnimatedPropertiesForSVGScriptElement();
53 }
54
55 PassRefPtr<SVGScriptElement> SVGScriptElement::create(const QualifiedName& tagName, Document* document, bool insertedByParser)
56 {
57     return adoptRef(new SVGScriptElement(tagName, document, insertedByParser, false));
58 }
59
60 bool SVGScriptElement::isSupportedAttribute(const QualifiedName& attrName)
61 {
62     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
63     if (supportedAttributes.isEmpty()) {
64         SVGURIReference::addSupportedAttributes(supportedAttributes);
65         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
66         supportedAttributes.add(SVGNames::typeAttr);
67         supportedAttributes.add(HTMLNames::onerrorAttr);
68     }
69     return supportedAttributes.contains(attrName);
70 }
71
72 void SVGScriptElement::parseMappedAttribute(Attribute* attr)
73 {
74     if (!isSupportedAttribute(attr->name())) {
75         SVGElement::parseMappedAttribute(attr);
76         return;
77     }
78
79     if (attr->name() == SVGNames::typeAttr) {
80         setType(attr->value());
81         return;
82     }
83
84     if (attr->name() == HTMLNames::onerrorAttr) {
85         setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attr));
86         return;
87     }
88
89     if (SVGURIReference::parseMappedAttribute(attr))
90         return;
91     if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
92         return;
93
94     ASSERT_NOT_REACHED();
95 }
96
97 void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
98 {
99     if (!isSupportedAttribute(attrName)) {
100         SVGElement::svgAttributeChanged(attrName);
101         return;
102     }
103
104     SVGElementInstance::InvalidationGuard invalidationGuard(this);
105
106     if (attrName == SVGNames::typeAttr || attrName == HTMLNames::onerrorAttr)
107         return;
108
109     if (SVGURIReference::isKnownAttribute(attrName)) {
110         handleSourceAttribute(href());
111         return;
112     }
113
114     if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
115         // Handle dynamic updates of the 'externalResourcesRequired' attribute. Only possible case: changing from 'true' to 'false'
116         // causes an immediate dispatch of the SVGLoad event. If the attribute value was 'false' before inserting the script element
117         // in the document, the SVGLoad event has already been dispatched.
118         if (!externalResourcesRequiredBaseValue() && !haveFiredLoadEvent() && !isParserInserted()) {
119             setHaveFiredLoadEvent(true);
120             ASSERT(haveLoadedRequiredResources());
121
122             sendSVGLoadEventIfPossible();
123         }
124         return;
125     }
126
127     ASSERT_NOT_REACHED();
128 }
129
130 void SVGScriptElement::insertedIntoDocument()
131 {
132     SVGElement::insertedIntoDocument();
133     ScriptElement::insertedIntoDocument();
134
135     if (isParserInserted())
136         return;
137
138     // Eventually send SVGLoad event now for the dynamically inserted script element
139     if (!externalResourcesRequiredBaseValue()) {
140         setHaveFiredLoadEvent(true);
141         sendSVGLoadEventIfPossible();
142     }
143 }
144
145 void SVGScriptElement::removedFromDocument()
146 {
147     SVGElement::removedFromDocument();
148     ScriptElement::removedFromDocument();
149 }
150
151 void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
152 {
153     ScriptElement::childrenChanged();
154     SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
155 }
156
157 bool SVGScriptElement::isURLAttribute(Attribute* attr) const
158 {
159     return attr->name() == sourceAttributeValue();
160 }
161
162 void SVGScriptElement::finishParsingChildren()
163 {
164     SVGElement::finishParsingChildren();
165
166     // A SVGLoad event has been fired by SVGElement::finishParsingChildren.
167     if (!externalResourcesRequiredBaseValue())
168         setHaveFiredLoadEvent(true);
169 }
170
171 String SVGScriptElement::type() const
172 {
173     return m_type;
174 }
175
176 void SVGScriptElement::setType(const String& type)
177 {
178     m_type = type;
179 }
180
181 void SVGScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
182 {
183     SVGElement::addSubresourceAttributeURLs(urls);
184
185     addSubresourceURL(urls, document()->completeURL(href()));
186 }
187
188 bool SVGScriptElement::haveLoadedRequiredResources()
189 {
190     return !externalResourcesRequiredBaseValue() || haveFiredLoadEvent();
191 }
192
193 String SVGScriptElement::sourceAttributeValue() const
194 {
195     return href();
196 }
197
198 String SVGScriptElement::charsetAttributeValue() const
199 {
200     return String();
201 }
202
203 String SVGScriptElement::typeAttributeValue() const
204 {
205     return type();
206 }
207
208 String SVGScriptElement::languageAttributeValue() const
209 {
210     return String();
211 }
212
213 String SVGScriptElement::forAttributeValue() const
214 {
215     return String();
216 }
217
218 String SVGScriptElement::eventAttributeValue() const
219 {
220     return String();
221 }
222
223 bool SVGScriptElement::asyncAttributeValue() const
224 {
225     return false;
226 }
227
228 bool SVGScriptElement::deferAttributeValue() const
229 {
230     return false;
231 }
232
233 bool SVGScriptElement::hasSourceAttribute() const
234 {
235     return hasAttribute(XLinkNames::hrefAttr);
236 }
237
238 void SVGScriptElement::dispatchLoadEvent()
239 {
240     bool externalResourcesRequired = externalResourcesRequiredBaseValue();
241
242     if (isParserInserted())
243         ASSERT(externalResourcesRequired != haveFiredLoadEvent());
244     else if (haveFiredLoadEvent()) {
245         // If we've already fired an load event and externalResourcesRequired is set to 'true'
246         // externalResourcesRequired has been modified while loading the <script>. Don't dispatch twice.
247         if (externalResourcesRequired)
248             return;
249     }
250
251     // HTML and SVG differ completly in the 'onload' event handling of <script> elements.
252     // HTML fires the 'load' event after it sucessfully loaded a remote resource, otherwhise an error event.
253     // SVG fires the SVGLoad event immediately after parsing the <script> element, if externalResourcesRequired
254     // is set to 'false', otherwhise it dispatches the 'SVGLoad' event just after loading the remote resource.
255     if (externalResourcesRequired) {
256         ASSERT(!haveFiredLoadEvent());
257
258         // Dispatch SVGLoad event
259         setHaveFiredLoadEvent(true);
260         ASSERT(haveLoadedRequiredResources());
261
262         sendSVGLoadEventIfPossible();
263     }
264 }
265
266 PassRefPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren()
267 {
268     return adoptRef(new SVGScriptElement(tagQName(), document(), false, alreadyStarted()));
269 }
270
271 }
272
273 #endif // ENABLE(SVG)