1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsScriptElement.h"
8 #include "mozilla/BasicEvents.h"
9 #include "mozilla/EventDispatcher.h"
10 #include "mozilla/dom/Element.h"
11 #include "nsContentUtils.h"
12 #include "nsPresContext.h"
13 #include "nsScriptLoader.h"
14 #include "nsIParser.h"
15 #include "nsGkAtoms.h"
16 #include "nsContentSink.h"
17
18 using namespace mozilla;
19 using namespace mozilla::dom;
20
21 NS_IMETHODIMP
ScriptAvailable(nsresult aResult,nsIScriptElement * aElement,bool aIsInline,nsIURI * aURI,int32_t aLineNo)22 nsScriptElement::ScriptAvailable(nsresult aResult,
23 nsIScriptElement *aElement,
24 bool aIsInline,
25 nsIURI *aURI,
26 int32_t aLineNo)
27 {
28 if (!aIsInline && NS_FAILED(aResult)) {
29 nsCOMPtr<nsIParser> parser = do_QueryReferent(mCreatorParser);
30 if (parser) {
31 parser->PushDefinedInsertionPoint();
32 }
33 nsresult rv = FireErrorEvent();
34 if (parser) {
35 parser->PopDefinedInsertionPoint();
36 }
37 return rv;
38 }
39 return NS_OK;
40 }
41
42 /* virtual */ nsresult
FireErrorEvent()43 nsScriptElement::FireErrorEvent()
44 {
45 nsCOMPtr<nsIContent> cont =
46 do_QueryInterface((nsIScriptElement*) this);
47
48 return nsContentUtils::DispatchTrustedEvent(cont->OwnerDoc(),
49 cont,
50 NS_LITERAL_STRING("error"),
51 false /* bubbles */,
52 false /* cancelable */);
53 }
54
55 NS_IMETHODIMP
ScriptEvaluated(nsresult aResult,nsIScriptElement * aElement,bool aIsInline)56 nsScriptElement::ScriptEvaluated(nsresult aResult,
57 nsIScriptElement *aElement,
58 bool aIsInline)
59 {
60 nsresult rv = NS_OK;
61 if (!aIsInline) {
62 nsCOMPtr<nsIContent> cont =
63 do_QueryInterface((nsIScriptElement*) this);
64
65 RefPtr<nsPresContext> presContext =
66 nsContentUtils::GetContextForContent(cont);
67
68 nsEventStatus status = nsEventStatus_eIgnore;
69 EventMessage message = NS_SUCCEEDED(aResult) ? eLoad : eLoadError;
70 WidgetEvent event(true, message);
71 // Load event doesn't bubble.
72 event.mFlags.mBubbles = (message != eLoad);
73
74 EventDispatcher::Dispatch(cont, presContext, &event, nullptr, &status);
75 }
76
77 return rv;
78 }
79
80 void
CharacterDataChanged(nsIDocument * aDocument,nsIContent * aContent,CharacterDataChangeInfo * aInfo)81 nsScriptElement::CharacterDataChanged(nsIDocument *aDocument,
82 nsIContent* aContent,
83 CharacterDataChangeInfo* aInfo)
84 {
85 MaybeProcessScript();
86 }
87
88 void
AttributeChanged(nsIDocument * aDocument,Element * aElement,int32_t aNameSpaceID,nsIAtom * aAttribute,int32_t aModType,const nsAttrValue * aOldValue)89 nsScriptElement::AttributeChanged(nsIDocument* aDocument,
90 Element* aElement,
91 int32_t aNameSpaceID,
92 nsIAtom* aAttribute,
93 int32_t aModType,
94 const nsAttrValue* aOldValue)
95 {
96 MaybeProcessScript();
97 }
98
99 void
ContentAppended(nsIDocument * aDocument,nsIContent * aContainer,nsIContent * aFirstNewContent,int32_t aNewIndexInContainer)100 nsScriptElement::ContentAppended(nsIDocument* aDocument,
101 nsIContent* aContainer,
102 nsIContent* aFirstNewContent,
103 int32_t aNewIndexInContainer)
104 {
105 MaybeProcessScript();
106 }
107
108 void
ContentInserted(nsIDocument * aDocument,nsIContent * aContainer,nsIContent * aChild,int32_t aIndexInContainer)109 nsScriptElement::ContentInserted(nsIDocument *aDocument,
110 nsIContent* aContainer,
111 nsIContent* aChild,
112 int32_t aIndexInContainer)
113 {
114 MaybeProcessScript();
115 }
116
117 bool
MaybeProcessScript()118 nsScriptElement::MaybeProcessScript()
119 {
120 nsCOMPtr<nsIContent> cont =
121 do_QueryInterface((nsIScriptElement*) this);
122
123 NS_ASSERTION(cont->DebugGetSlots()->mMutationObservers.Contains(this),
124 "You forgot to add self as observer");
125
126 if (mAlreadyStarted || !mDoneAddingChildren ||
127 !cont->GetComposedDoc() || mMalformed || !HasScriptContent()) {
128 return false;
129 }
130
131 FreezeUriAsyncDefer();
132
133 mAlreadyStarted = true;
134
135 nsIDocument* ownerDoc = cont->OwnerDoc();
136 nsCOMPtr<nsIParser> parser = ((nsIScriptElement*) this)->GetCreatorParser();
137 if (parser) {
138 nsCOMPtr<nsIContentSink> sink = parser->GetContentSink();
139 if (sink) {
140 nsCOMPtr<nsIDocument> parserDoc = do_QueryInterface(sink->GetTarget());
141 if (ownerDoc != parserDoc) {
142 // Willful violation of HTML5 as of 2010-12-01
143 return false;
144 }
145 }
146 }
147
148 RefPtr<nsScriptLoader> loader = ownerDoc->ScriptLoader();
149 return loader->ProcessScriptElement(this);
150 }
151