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#include "core/svg/SVGScriptElement.h"
24
25#include "HTMLNames.h"
26#include "XLinkNames.h"
27#include "bindings/v8/ScriptEventListener.h"
28#include "core/dom/Attribute.h"
29#include "core/dom/Document.h"
30#include "core/dom/EventNames.h"
31#include "core/dom/ScriptLoader.h"
32#include "core/svg/SVGElementInstance.h"
33#include "core/svg/properties/SVGAnimatedStaticPropertyTearOff.h"
34
35namespace WebCore {
36
37// Animated property definitions
38DEFINE_ANIMATED_STRING(SVGScriptElement, XLinkNames::hrefAttr, Href, href)
39DEFINE_ANIMATED_BOOLEAN(SVGScriptElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
40
41BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGScriptElement)
42    REGISTER_LOCAL_ANIMATED_PROPERTY(href)
43    REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
44END_REGISTER_ANIMATED_PROPERTIES
45
46inline SVGScriptElement::SVGScriptElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser, bool alreadyStarted)
47    : SVGElement(tagName, document)
48    , m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired)
49    , m_loader(ScriptLoader::create(this, wasInsertedByParser, alreadyStarted))
50{
51    ASSERT(hasTagName(SVGNames::scriptTag));
52    ScriptWrappable::init(this);
53    registerAnimatedPropertiesForSVGScriptElement();
54}
55
56PassRefPtr<SVGScriptElement> SVGScriptElement::create(const QualifiedName& tagName, Document* document, bool insertedByParser)
57{
58    return adoptRef(new SVGScriptElement(tagName, document, insertedByParser, false));
59}
60
61bool SVGScriptElement::isSupportedAttribute(const QualifiedName& attrName)
62{
63    DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
64    if (supportedAttributes.isEmpty()) {
65        SVGURIReference::addSupportedAttributes(supportedAttributes);
66        SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
67        supportedAttributes.add(SVGNames::typeAttr);
68        supportedAttributes.add(HTMLNames::onerrorAttr);
69    }
70    return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
71}
72
73void SVGScriptElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
74{
75    if (!isSupportedAttribute(name)) {
76        SVGElement::parseAttribute(name, value);
77        return;
78    }
79
80    if (name == SVGNames::typeAttr) {
81        setType(value);
82        return;
83    }
84
85    if (name == HTMLNames::onerrorAttr) {
86        setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, name, value));
87        return;
88    }
89
90    if (SVGURIReference::parseAttribute(name, value))
91        return;
92    if (SVGExternalResourcesRequired::parseAttribute(name, value))
93        return;
94
95    ASSERT_NOT_REACHED();
96}
97
98void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName)
99{
100    if (!isSupportedAttribute(attrName)) {
101        SVGElement::svgAttributeChanged(attrName);
102        return;
103    }
104
105    SVGElementInstance::InvalidationGuard invalidationGuard(this);
106
107    if (attrName == SVGNames::typeAttr || attrName == HTMLNames::onerrorAttr)
108        return;
109
110    if (SVGURIReference::isKnownAttribute(attrName)) {
111        m_loader->handleSourceAttribute(hrefCurrentValue());
112        return;
113    }
114
115    if (SVGExternalResourcesRequired::handleAttributeChange(this, attrName))
116        return;
117
118    ASSERT_NOT_REACHED();
119}
120
121Node::InsertionNotificationRequest SVGScriptElement::insertedInto(ContainerNode* rootParent)
122{
123    SVGElement::insertedInto(rootParent);
124    m_loader->insertedInto(rootParent);
125    if (rootParent->inDocument())
126        SVGExternalResourcesRequired::insertedIntoDocument(this);
127    return InsertionDone;
128}
129
130void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
131{
132    SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
133    m_loader->childrenChanged();
134}
135
136bool SVGScriptElement::isURLAttribute(const Attribute& attribute) const
137{
138    return attribute.name() == sourceAttributeValue();
139}
140
141void SVGScriptElement::finishParsingChildren()
142{
143    SVGElement::finishParsingChildren();
144    SVGExternalResourcesRequired::finishParsingChildren();
145}
146
147String SVGScriptElement::type() const
148{
149    return m_type;
150}
151
152void SVGScriptElement::setType(const String& type)
153{
154    m_type = type;
155}
156
157void SVGScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
158{
159    SVGElement::addSubresourceAttributeURLs(urls);
160
161    addSubresourceURL(urls, document()->completeURL(hrefCurrentValue()));
162}
163
164String SVGScriptElement::sourceAttributeValue() const
165{
166    return hrefCurrentValue();
167}
168
169String SVGScriptElement::charsetAttributeValue() const
170{
171    return String();
172}
173
174String SVGScriptElement::typeAttributeValue() const
175{
176    return type();
177}
178
179String SVGScriptElement::languageAttributeValue() const
180{
181    return String();
182}
183
184String SVGScriptElement::forAttributeValue() const
185{
186    return String();
187}
188
189String SVGScriptElement::eventAttributeValue() const
190{
191    return String();
192}
193
194bool SVGScriptElement::asyncAttributeValue() const
195{
196    return false;
197}
198
199bool SVGScriptElement::deferAttributeValue() const
200{
201    return false;
202}
203
204bool SVGScriptElement::hasSourceAttribute() const
205{
206    return hasAttribute(XLinkNames::hrefAttr);
207}
208
209PassRefPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren()
210{
211    return adoptRef(new SVGScriptElement(tagQName(), document(), false, m_loader->alreadyStarted()));
212}
213
214void SVGScriptElement::setHaveFiredLoadEvent(bool haveFiredLoadEvent)
215{
216    m_loader->setHaveFiredLoadEvent(haveFiredLoadEvent);
217}
218
219bool SVGScriptElement::isParserInserted() const
220{
221    return m_loader->isParserInserted();
222}
223
224bool SVGScriptElement::haveFiredLoadEvent() const
225{
226    return m_loader->haveFiredLoadEvent();
227}
228
229Timer<SVGElement>* SVGScriptElement::svgLoadEventTimer()
230{
231    return &m_svgLoadEventTimer;
232}
233
234}
235