1 /* 2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2007 Rob Buis <buis (at) 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 "bindings/v8/ScriptEventListener.h" 26 #include "core/HTMLNames.h" 27 #include "core/XLinkNames.h" 28 #include "core/dom/Attribute.h" 29 #include "core/dom/Document.h" 30 #include "core/dom/ScriptLoader.h" 31 32 namespace WebCore { 33 34 inline SVGScriptElement::SVGScriptElement(Document& document, bool wasInsertedByParser, bool alreadyStarted) 35 : SVGElement(SVGNames::scriptTag, document) 36 , SVGURIReference(this) 37 , m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired) 38 , m_loader(ScriptLoader::create(this, wasInsertedByParser, alreadyStarted)) 39 { 40 ScriptWrappable::init(this); 41 } 42 43 PassRefPtrWillBeRawPtr<SVGScriptElement> SVGScriptElement::create(Document& document, bool insertedByParser) 44 { 45 return adoptRefWillBeNoop(new SVGScriptElement(document, insertedByParser, false)); 46 } 47 48 bool SVGScriptElement::isSupportedAttribute(const QualifiedName& attrName) 49 { 50 DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ()); 51 if (supportedAttributes.isEmpty()) { 52 SVGURIReference::addSupportedAttributes(supportedAttributes); 53 supportedAttributes.add(SVGNames::typeAttr); 54 supportedAttributes.add(HTMLNames::onerrorAttr); 55 } 56 return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName); 57 } 58 59 void SVGScriptElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 60 { 61 if (!isSupportedAttribute(name)) { 62 SVGElement::parseAttribute(name, value); 63 return; 64 } 65 66 SVGParsingError parseError = NoError; 67 if (name == SVGNames::typeAttr) 68 return; 69 70 if (name == HTMLNames::onerrorAttr) { 71 setAttributeEventListener(EventTypeNames::error, createAttributeEventListener(this, name, value, eventParameterName())); 72 } else if (SVGURIReference::parseAttribute(name, value, parseError)) { 73 } else { 74 ASSERT_NOT_REACHED(); 75 } 76 77 reportAttributeParsingError(parseError, name, value); 78 } 79 80 void SVGScriptElement::svgAttributeChanged(const QualifiedName& attrName) 81 { 82 if (!isSupportedAttribute(attrName)) { 83 SVGElement::svgAttributeChanged(attrName); 84 return; 85 } 86 87 SVGElement::InvalidationGuard invalidationGuard(this); 88 89 if (attrName == SVGNames::typeAttr || attrName == HTMLNames::onerrorAttr) 90 return; 91 92 if (SVGURIReference::isKnownAttribute(attrName)) { 93 m_loader->handleSourceAttribute(hrefString()); 94 return; 95 } 96 97 ASSERT_NOT_REACHED(); 98 } 99 100 Node::InsertionNotificationRequest SVGScriptElement::insertedInto(ContainerNode* rootParent) 101 { 102 SVGElement::insertedInto(rootParent); 103 return InsertionShouldCallDidNotifySubtreeInsertions; 104 } 105 106 void SVGScriptElement::didNotifySubtreeInsertionsToDocument() 107 { 108 m_loader->didNotifySubtreeInsertionsToDocument(); 109 110 if (!m_loader->isParserInserted()) { 111 m_loader->setHaveFiredLoadEvent(true); 112 sendSVGLoadEventIfPossibleAsynchronously(); 113 } 114 } 115 116 void SVGScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 117 { 118 SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 119 m_loader->childrenChanged(); 120 } 121 122 bool SVGScriptElement::isURLAttribute(const Attribute& attribute) const 123 { 124 return attribute.name() == AtomicString(sourceAttributeValue()); 125 } 126 127 void SVGScriptElement::finishParsingChildren() 128 { 129 SVGElement::finishParsingChildren(); 130 m_loader->setHaveFiredLoadEvent(true); 131 } 132 133 bool SVGScriptElement::haveLoadedRequiredResources() 134 { 135 return m_loader->haveFiredLoadEvent(); 136 } 137 138 String SVGScriptElement::sourceAttributeValue() const 139 { 140 return hrefString(); 141 } 142 143 String SVGScriptElement::charsetAttributeValue() const 144 { 145 return String(); 146 } 147 148 String SVGScriptElement::typeAttributeValue() const 149 { 150 return getAttribute(SVGNames::typeAttr).string(); 151 } 152 153 String SVGScriptElement::languageAttributeValue() const 154 { 155 return String(); 156 } 157 158 String SVGScriptElement::forAttributeValue() const 159 { 160 return String(); 161 } 162 163 String SVGScriptElement::eventAttributeValue() const 164 { 165 return String(); 166 } 167 168 bool SVGScriptElement::asyncAttributeValue() const 169 { 170 return false; 171 } 172 173 bool SVGScriptElement::deferAttributeValue() const 174 { 175 return false; 176 } 177 178 bool SVGScriptElement::hasSourceAttribute() const 179 { 180 return href()->isSpecified(); 181 } 182 183 PassRefPtrWillBeRawPtr<Element> SVGScriptElement::cloneElementWithoutAttributesAndChildren() 184 { 185 return adoptRefWillBeNoop(new SVGScriptElement(document(), false, m_loader->alreadyStarted())); 186 } 187 188 void SVGScriptElement::dispatchLoadEvent() 189 { 190 dispatchEvent(Event::create(EventTypeNames::load)); 191 } 192 193 #ifndef NDEBUG 194 bool SVGScriptElement::isAnimatableAttribute(const QualifiedName& name) const 195 { 196 if (name == SVGNames::typeAttr) 197 return false; 198 199 return SVGElement::isAnimatableAttribute(name); 200 } 201 #endif 202 203 } 204