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