1 /* 2 * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 1999 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2001 Dirk Mueller (mueller (at) kde.org) 5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Library General Public 9 * License as published by the Free Software Foundation; either 10 * version 2 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Library General Public License for more details. 16 * 17 * You should have received a copy of the GNU Library General Public License 18 * along with this library; see the file COPYING.LIB. If not, write to 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20 * Boston, MA 02110-1301, USA. 21 */ 22 23 #include "config.h" 24 #include "HTMLScriptElement.h" 25 26 #include "Attribute.h" 27 #include "Document.h" 28 #include "Event.h" 29 #include "EventNames.h" 30 #include "HTMLNames.h" 31 #include "ScriptEventListener.h" 32 #include "Settings.h" 33 #include "Text.h" 34 35 namespace WebCore { 36 37 using namespace HTMLNames; 38 39 inline HTMLScriptElement::HTMLScriptElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser, bool alreadyStarted) 40 : HTMLElement(tagName, document) 41 , ScriptElement(this, wasInsertedByParser, alreadyStarted) 42 { 43 ASSERT(hasTagName(scriptTag)); 44 } 45 46 PassRefPtr<HTMLScriptElement> HTMLScriptElement::create(const QualifiedName& tagName, Document* document, bool wasInsertedByParser) 47 { 48 return adoptRef(new HTMLScriptElement(tagName, document, wasInsertedByParser, false)); 49 } 50 51 bool HTMLScriptElement::isURLAttribute(Attribute* attr) const 52 { 53 return attr->name() == srcAttr; 54 } 55 56 void HTMLScriptElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) 57 { 58 ScriptElement::childrenChanged(); 59 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); 60 } 61 62 void HTMLScriptElement::attributeChanged(Attribute* attr, bool preserveDecls) 63 { 64 if (attr->name() == asyncAttr) 65 handleAsyncAttribute(); 66 HTMLElement::attributeChanged(attr, preserveDecls); 67 } 68 69 void HTMLScriptElement::parseMappedAttribute(Attribute* attr) 70 { 71 const QualifiedName& attrName = attr->name(); 72 73 if (attrName == srcAttr) 74 handleSourceAttribute(attr->value()); 75 else if (attrName == onloadAttr) 76 setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attr)); 77 else if (attrName == onbeforeloadAttr) 78 setAttributeEventListener(eventNames().beforeloadEvent, createAttributeEventListener(this, attr)); 79 else if (attrName == onbeforeprocessAttr) 80 setAttributeEventListener(eventNames().beforeprocessEvent, createAttributeEventListener(this, attr)); 81 else 82 HTMLElement::parseMappedAttribute(attr); 83 } 84 85 static bool needsOldRequirejsQuirk(HTMLScriptElement* element) 86 { 87 if (element->fastGetAttribute(typeAttr) != "script/cache") 88 return false; 89 90 Document* document = element->document(); 91 92 const KURL& url = document->url(); 93 if (!equalIgnoringCase(url.host(), "www.zipcar.com")) 94 return false; 95 96 Settings* settings = document->settings(); 97 if (!settings) 98 return false; 99 if (!settings->needsSiteSpecificQuirks()) 100 return false; 101 102 return true; 103 } 104 105 void HTMLScriptElement::insertedIntoDocument() 106 { 107 if (needsOldRequirejsQuirk(this)) { 108 if (!asyncAttributeValue()) 109 handleAsyncAttribute(); // Clear forceAsync, so this script loads in parallel, but executes in order. 110 setAttribute(typeAttr, "text/javascript"); 111 } 112 HTMLElement::insertedIntoDocument(); 113 ScriptElement::insertedIntoDocument(); 114 } 115 116 void HTMLScriptElement::removedFromDocument() 117 { 118 HTMLElement::removedFromDocument(); 119 ScriptElement::removedFromDocument(); 120 } 121 122 void HTMLScriptElement::setText(const String &value) 123 { 124 ExceptionCode ec = 0; 125 int numChildren = childNodeCount(); 126 127 if (numChildren == 1 && firstChild()->isTextNode()) { 128 static_cast<Text*>(firstChild())->setData(value, ec); 129 return; 130 } 131 132 if (numChildren > 0) 133 removeChildren(); 134 135 appendChild(document()->createTextNode(value.impl()), ec); 136 } 137 138 void HTMLScriptElement::setAsync(bool async) 139 { 140 setBooleanAttribute(asyncAttr, async); 141 handleAsyncAttribute(); 142 } 143 144 bool HTMLScriptElement::async() const 145 { 146 return fastHasAttribute(asyncAttr) || forceAsync(); 147 } 148 149 KURL HTMLScriptElement::src() const 150 { 151 return document()->completeURL(sourceAttributeValue()); 152 } 153 154 void HTMLScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 155 { 156 HTMLElement::addSubresourceAttributeURLs(urls); 157 158 addSubresourceURL(urls, src()); 159 } 160 161 String HTMLScriptElement::sourceAttributeValue() const 162 { 163 return getAttribute(srcAttr).string(); 164 } 165 166 String HTMLScriptElement::charsetAttributeValue() const 167 { 168 return getAttribute(charsetAttr).string(); 169 } 170 171 String HTMLScriptElement::typeAttributeValue() const 172 { 173 return getAttribute(typeAttr).string(); 174 } 175 176 String HTMLScriptElement::languageAttributeValue() const 177 { 178 return getAttribute(languageAttr).string(); 179 } 180 181 String HTMLScriptElement::forAttributeValue() const 182 { 183 return getAttribute(forAttr).string(); 184 } 185 186 String HTMLScriptElement::eventAttributeValue() const 187 { 188 return getAttribute(eventAttr).string(); 189 } 190 191 bool HTMLScriptElement::asyncAttributeValue() const 192 { 193 return fastHasAttribute(asyncAttr); 194 } 195 196 bool HTMLScriptElement::deferAttributeValue() const 197 { 198 return fastHasAttribute(deferAttr); 199 } 200 201 bool HTMLScriptElement::hasSourceAttribute() const 202 { 203 return fastHasAttribute(srcAttr); 204 } 205 206 void HTMLScriptElement::dispatchLoadEvent() 207 { 208 ASSERT(!haveFiredLoadEvent()); 209 setHaveFiredLoadEvent(true); 210 211 dispatchEvent(Event::create(eventNames().loadEvent, false, false)); 212 } 213 214 void HTMLScriptElement::dispatchErrorEvent() 215 { 216 dispatchEvent(Event::create(eventNames().errorEvent, true, false)); 217 } 218 219 PassRefPtr<Element> HTMLScriptElement::cloneElementWithoutAttributesAndChildren() const 220 { 221 return adoptRef(new HTMLScriptElement(tagQName(), document(), false, alreadyStarted())); 222 } 223 224 } 225