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