1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@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
HTMLScriptElement(const QualifiedName & tagName,Document * document,bool wasInsertedByParser,bool alreadyStarted)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
create(const QualifiedName & tagName,Document * document,bool wasInsertedByParser)46 PassRefPtr<HTMLScriptElement> HTMLScriptElement::create(const QualifiedName& tagName, Document* document, bool wasInsertedByParser)
47 {
48 return adoptRef(new HTMLScriptElement(tagName, document, wasInsertedByParser, false));
49 }
50
isURLAttribute(Attribute * attr) const51 bool HTMLScriptElement::isURLAttribute(Attribute* attr) const
52 {
53 return attr->name() == srcAttr;
54 }
55
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)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
attributeChanged(Attribute * attr,bool preserveDecls)62 void HTMLScriptElement::attributeChanged(Attribute* attr, bool preserveDecls)
63 {
64 if (attr->name() == asyncAttr)
65 handleAsyncAttribute();
66 HTMLElement::attributeChanged(attr, preserveDecls);
67 }
68
parseMappedAttribute(Attribute * attr)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
needsOldRequirejsQuirk(HTMLScriptElement * element)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
insertedIntoDocument()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
removedFromDocument()116 void HTMLScriptElement::removedFromDocument()
117 {
118 HTMLElement::removedFromDocument();
119 ScriptElement::removedFromDocument();
120 }
121
setText(const String & value)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
setAsync(bool async)138 void HTMLScriptElement::setAsync(bool async)
139 {
140 setBooleanAttribute(asyncAttr, async);
141 handleAsyncAttribute();
142 }
143
async() const144 bool HTMLScriptElement::async() const
145 {
146 return fastHasAttribute(asyncAttr) || forceAsync();
147 }
148
src() const149 KURL HTMLScriptElement::src() const
150 {
151 return document()->completeURL(sourceAttributeValue());
152 }
153
addSubresourceAttributeURLs(ListHashSet<KURL> & urls) const154 void HTMLScriptElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
155 {
156 HTMLElement::addSubresourceAttributeURLs(urls);
157
158 addSubresourceURL(urls, src());
159 }
160
sourceAttributeValue() const161 String HTMLScriptElement::sourceAttributeValue() const
162 {
163 return getAttribute(srcAttr).string();
164 }
165
charsetAttributeValue() const166 String HTMLScriptElement::charsetAttributeValue() const
167 {
168 return getAttribute(charsetAttr).string();
169 }
170
typeAttributeValue() const171 String HTMLScriptElement::typeAttributeValue() const
172 {
173 return getAttribute(typeAttr).string();
174 }
175
languageAttributeValue() const176 String HTMLScriptElement::languageAttributeValue() const
177 {
178 return getAttribute(languageAttr).string();
179 }
180
forAttributeValue() const181 String HTMLScriptElement::forAttributeValue() const
182 {
183 return getAttribute(forAttr).string();
184 }
185
eventAttributeValue() const186 String HTMLScriptElement::eventAttributeValue() const
187 {
188 return getAttribute(eventAttr).string();
189 }
190
asyncAttributeValue() const191 bool HTMLScriptElement::asyncAttributeValue() const
192 {
193 return fastHasAttribute(asyncAttr);
194 }
195
deferAttributeValue() const196 bool HTMLScriptElement::deferAttributeValue() const
197 {
198 return fastHasAttribute(deferAttr);
199 }
200
hasSourceAttribute() const201 bool HTMLScriptElement::hasSourceAttribute() const
202 {
203 return fastHasAttribute(srcAttr);
204 }
205
dispatchLoadEvent()206 void HTMLScriptElement::dispatchLoadEvent()
207 {
208 ASSERT(!haveFiredLoadEvent());
209 setHaveFiredLoadEvent(true);
210
211 dispatchEvent(Event::create(eventNames().loadEvent, false, false));
212 }
213
dispatchErrorEvent()214 void HTMLScriptElement::dispatchErrorEvent()
215 {
216 dispatchEvent(Event::create(eventNames().errorEvent, true, false));
217 }
218
cloneElementWithoutAttributesAndChildren() const219 PassRefPtr<Element> HTMLScriptElement::cloneElementWithoutAttributesAndChildren() const
220 {
221 return adoptRef(new HTMLScriptElement(tagQName(), document(), false, alreadyStarted()));
222 }
223
224 }
225