1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 sw=2 et tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is Mozilla Communicator client code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 : #include "nsIDOMHTMLScriptElement.h"
39 : #include "nsIDOMEventTarget.h"
40 : #include "nsGenericHTMLElement.h"
41 : #include "nsGkAtoms.h"
42 : #include "nsStyleConsts.h"
43 : #include "nsIDocument.h"
44 : #include "nsScriptElement.h"
45 : #include "nsIURI.h"
46 : #include "nsNetUtil.h"
47 : #include "nsContentUtils.h"
48 : #include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator()
49 : #include "jsapi.h"
50 : #include "nsIScriptContext.h"
51 : #include "nsIScriptGlobalObject.h"
52 : #include "nsIXPConnect.h"
53 : #include "nsServiceManagerUtils.h"
54 : #include "nsIDOMDocument.h"
55 : #include "nsContentErrors.h"
56 : #include "nsIArray.h"
57 : #include "nsTArray.h"
58 : #include "nsDOMJSUtils.h"
59 :
60 : using namespace mozilla;
61 : using namespace mozilla::dom;
62 :
63 : class nsHTMLScriptElement : public nsGenericHTMLElement,
64 : public nsIDOMHTMLScriptElement,
65 : public nsScriptElement
66 : {
67 : public:
68 : using nsGenericElement::GetText;
69 : using nsGenericElement::SetText;
70 :
71 : nsHTMLScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
72 : FromParser aFromParser);
73 : virtual ~nsHTMLScriptElement();
74 :
75 : // nsISupports
76 : NS_DECL_ISUPPORTS_INHERITED
77 :
78 : // nsIDOMNode
79 0 : NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
80 :
81 : // nsIDOMElement
82 0 : NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
83 :
84 : // nsIDOMHTMLElement
85 0 : NS_FORWARD_NSIDOMHTMLELEMENT_BASIC(nsGenericHTMLElement::)
86 0 : NS_SCRIPTABLE NS_IMETHOD Click() {
87 0 : return nsGenericHTMLElement::Click();
88 : }
89 0 : NS_SCRIPTABLE NS_IMETHOD GetTabIndex(PRInt32* aTabIndex) {
90 0 : return nsGenericHTMLElement::GetTabIndex(aTabIndex);
91 : }
92 0 : NS_SCRIPTABLE NS_IMETHOD SetTabIndex(PRInt32 aTabIndex) {
93 0 : return nsGenericHTMLElement::SetTabIndex(aTabIndex);
94 : }
95 0 : NS_SCRIPTABLE NS_IMETHOD Focus() {
96 0 : return nsGenericHTMLElement::Focus();
97 : }
98 0 : NS_SCRIPTABLE NS_IMETHOD GetDraggable(bool* aDraggable) {
99 0 : return nsGenericHTMLElement::GetDraggable(aDraggable);
100 : }
101 : NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
102 : NS_SCRIPTABLE NS_IMETHOD SetInnerHTML(const nsAString& aInnerHTML);
103 :
104 : // nsIDOMHTMLScriptElement
105 : NS_DECL_NSIDOMHTMLSCRIPTELEMENT
106 :
107 : // nsIScriptElement
108 : virtual void GetScriptType(nsAString& type);
109 : virtual void GetScriptText(nsAString& text);
110 : virtual void GetScriptCharset(nsAString& charset);
111 : virtual void FreezeUriAsyncDefer();
112 : virtual CORSMode GetCORSMode() const;
113 :
114 : // nsIContent
115 : virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
116 : nsIContent* aBindingParent,
117 : bool aCompileEventHandlers);
118 : virtual bool ParseAttribute(PRInt32 aNamespaceID,
119 : nsIAtom* aAttribute,
120 : const nsAString& aValue,
121 : nsAttrValue& aResult);
122 :
123 : virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
124 :
125 : // nsGenericElement
126 : virtual nsresult AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
127 : const nsAttrValue* aValue, bool aNotify);
128 :
129 : virtual nsXPCClassInfo* GetClassInfo();
130 : protected:
131 : // nsScriptElement
132 : virtual bool HasScriptContent();
133 : };
134 :
135 :
136 0 : NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Script)
137 :
138 :
139 0 : nsHTMLScriptElement::nsHTMLScriptElement(already_AddRefed<nsINodeInfo> aNodeInfo,
140 : FromParser aFromParser)
141 : : nsGenericHTMLElement(aNodeInfo)
142 0 : , nsScriptElement(aFromParser)
143 : {
144 0 : AddMutationObserver(this);
145 0 : }
146 :
147 0 : nsHTMLScriptElement::~nsHTMLScriptElement()
148 : {
149 0 : }
150 :
151 :
152 0 : NS_IMPL_ADDREF_INHERITED(nsHTMLScriptElement, nsGenericElement)
153 0 : NS_IMPL_RELEASE_INHERITED(nsHTMLScriptElement, nsGenericElement)
154 :
155 0 : DOMCI_NODE_DATA(HTMLScriptElement, nsHTMLScriptElement)
156 :
157 : // QueryInterface implementation for nsHTMLScriptElement
158 0 : NS_INTERFACE_TABLE_HEAD(nsHTMLScriptElement)
159 0 : NS_HTML_CONTENT_INTERFACE_TABLE4(nsHTMLScriptElement,
160 : nsIDOMHTMLScriptElement,
161 : nsIScriptLoaderObserver,
162 : nsIScriptElement,
163 : nsIMutationObserver)
164 0 : NS_HTML_CONTENT_INTERFACE_TABLE_TO_MAP_SEGUE(nsHTMLScriptElement,
165 : nsGenericHTMLElement)
166 0 : NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(HTMLScriptElement)
167 0 : NS_HTML_CONTENT_INTERFACE_MAP_END
168 :
169 :
170 : nsresult
171 0 : nsHTMLScriptElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
172 : nsIContent* aBindingParent,
173 : bool aCompileEventHandlers)
174 : {
175 : nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
176 : aBindingParent,
177 0 : aCompileEventHandlers);
178 0 : NS_ENSURE_SUCCESS(rv, rv);
179 :
180 0 : if (aDocument) {
181 0 : MaybeProcessScript();
182 : }
183 :
184 0 : return NS_OK;
185 : }
186 :
187 : bool
188 0 : nsHTMLScriptElement::ParseAttribute(PRInt32 aNamespaceID,
189 : nsIAtom* aAttribute,
190 : const nsAString& aValue,
191 : nsAttrValue& aResult)
192 : {
193 0 : if (aNamespaceID == kNameSpaceID_None &&
194 : aAttribute == nsGkAtoms::crossorigin) {
195 0 : ParseCORSValue(aValue, aResult);
196 0 : return true;
197 : }
198 :
199 : return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
200 0 : aResult);
201 : }
202 :
203 : nsresult
204 0 : nsHTMLScriptElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const
205 : {
206 0 : *aResult = nsnull;
207 :
208 0 : nsCOMPtr<nsINodeInfo> ni = aNodeInfo;
209 : nsHTMLScriptElement* it =
210 0 : new nsHTMLScriptElement(ni.forget(), NOT_FROM_PARSER);
211 :
212 0 : nsCOMPtr<nsINode> kungFuDeathGrip = it;
213 0 : nsresult rv = CopyInnerTo(it);
214 0 : NS_ENSURE_SUCCESS(rv, rv);
215 :
216 : // The clone should be marked evaluated if we are.
217 0 : it->mAlreadyStarted = mAlreadyStarted;
218 0 : it->mLineNumber = mLineNumber;
219 0 : it->mMalformed = mMalformed;
220 :
221 0 : kungFuDeathGrip.swap(*aResult);
222 :
223 0 : return NS_OK;
224 : }
225 :
226 : NS_IMETHODIMP
227 0 : nsHTMLScriptElement::GetText(nsAString& aValue)
228 : {
229 0 : nsContentUtils::GetNodeTextContent(this, false, aValue);
230 0 : return NS_OK;
231 : }
232 :
233 : NS_IMETHODIMP
234 0 : nsHTMLScriptElement::SetText(const nsAString& aValue)
235 : {
236 0 : return nsContentUtils::SetNodeTextContent(this, aValue, true);
237 : }
238 :
239 :
240 0 : NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Charset, charset)
241 0 : NS_IMPL_BOOL_ATTR(nsHTMLScriptElement, Defer, defer)
242 0 : NS_IMPL_URI_ATTR(nsHTMLScriptElement, Src, src)
243 0 : NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Type, type)
244 0 : NS_IMPL_STRING_ATTR(nsHTMLScriptElement, HtmlFor, _for)
245 0 : NS_IMPL_STRING_ATTR(nsHTMLScriptElement, Event, event)
246 :
247 : nsresult
248 0 : nsHTMLScriptElement::GetAsync(bool* aValue)
249 : {
250 0 : if (mForceAsync) {
251 0 : *aValue = true;
252 0 : return NS_OK;
253 : }
254 0 : return GetBoolAttr(nsGkAtoms::async, aValue);
255 : }
256 :
257 : nsresult
258 0 : nsHTMLScriptElement::SetAsync(bool aValue)
259 : {
260 0 : mForceAsync = false;
261 0 : return SetBoolAttr(nsGkAtoms::async, aValue);
262 : }
263 :
264 : nsresult
265 0 : nsHTMLScriptElement::AfterSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
266 : const nsAttrValue* aValue, bool aNotify)
267 : {
268 0 : if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) {
269 0 : mForceAsync = false;
270 : }
271 : return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
272 0 : aNotify);
273 : }
274 :
275 : nsresult
276 0 : nsHTMLScriptElement::GetInnerHTML(nsAString& aInnerHTML)
277 : {
278 0 : nsContentUtils::GetNodeTextContent(this, false, aInnerHTML);
279 0 : return NS_OK;
280 : }
281 :
282 : nsresult
283 0 : nsHTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML)
284 : {
285 0 : return nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
286 : }
287 :
288 : // variation of this code in nsSVGScriptElement - check if changes
289 : // need to be transfered when modifying
290 :
291 : void
292 0 : nsHTMLScriptElement::GetScriptType(nsAString& type)
293 : {
294 0 : GetType(type);
295 0 : }
296 :
297 : void
298 0 : nsHTMLScriptElement::GetScriptText(nsAString& text)
299 : {
300 0 : GetText(text);
301 0 : }
302 :
303 : void
304 0 : nsHTMLScriptElement::GetScriptCharset(nsAString& charset)
305 : {
306 0 : GetCharset(charset);
307 0 : }
308 :
309 : void
310 0 : nsHTMLScriptElement::FreezeUriAsyncDefer()
311 : {
312 0 : if (mFrozen) {
313 0 : return;
314 : }
315 :
316 : // variation of this code in nsSVGScriptElement - check if changes
317 : // need to be transfered when modifying
318 0 : if (HasAttr(kNameSpaceID_None, nsGkAtoms::src)) {
319 0 : nsAutoString src;
320 0 : GetSrc(src);
321 0 : NS_NewURI(getter_AddRefs(mUri), src);
322 : // At this point mUri will be null for invalid URLs.
323 0 : mExternal = true;
324 :
325 : bool defer, async;
326 0 : GetAsync(&async);
327 0 : GetDefer(&defer);
328 :
329 0 : mDefer = !async && defer;
330 0 : mAsync = async;
331 : }
332 :
333 0 : mFrozen = true;
334 : }
335 :
336 : CORSMode
337 0 : nsHTMLScriptElement::GetCORSMode() const
338 : {
339 0 : return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
340 : }
341 :
342 : bool
343 0 : nsHTMLScriptElement::HasScriptContent()
344 : {
345 0 : return (mFrozen ? mExternal : HasAttr(kNameSpaceID_None, nsGkAtoms::src)) ||
346 0 : nsContentUtils::HasNonEmptyTextContent(this);
347 : }
|