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