1 /*
2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "third_party/blink/renderer/core/svg/svg_script_element.h"
22
23 #include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h"
24 #include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h"
25 #include "third_party/blink/renderer/core/dom/attribute.h"
26 #include "third_party/blink/renderer/core/dom/document.h"
27 #include "third_party/blink/renderer/core/dom/events/event.h"
28 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
29 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
30 #include "third_party/blink/renderer/core/html_names.h"
31 #include "third_party/blink/renderer/core/script/script_loader.h"
32 #include "third_party/blink/renderer/core/script/script_runner.h"
33 #include "third_party/blink/renderer/core/xlink_names.h"
34
35 namespace blink {
36
SVGScriptElement(Document & document,const CreateElementFlags flags)37 SVGScriptElement::SVGScriptElement(Document& document,
38 const CreateElementFlags flags)
39 : SVGElement(svg_names::kScriptTag, document),
40 SVGURIReference(this),
41 loader_(InitializeScriptLoader(flags)) {}
42
ParseAttribute(const AttributeModificationParams & params)43 void SVGScriptElement::ParseAttribute(
44 const AttributeModificationParams& params) {
45 if (params.name == html_names::kOnerrorAttr) {
46 SetAttributeEventListener(
47 event_type_names::kError,
48 JSEventHandlerForContentAttribute::Create(
49 GetExecutionContext(), params.name, params.new_value,
50 JSEventHandler::HandlerType::kOnErrorEventHandler));
51 } else {
52 SVGElement::ParseAttribute(params);
53 }
54 }
55
SvgAttributeChanged(const QualifiedName & attr_name)56 void SVGScriptElement::SvgAttributeChanged(const QualifiedName& attr_name) {
57 if (SVGURIReference::IsKnownAttribute(attr_name)) {
58 SVGElement::InvalidationGuard invalidation_guard(this);
59 loader_->HandleSourceAttribute(LegacyHrefString(*this));
60 return;
61 }
62
63 SVGElement::SvgAttributeChanged(attr_name);
64 }
65
InsertedInto(ContainerNode & root_parent)66 Node::InsertionNotificationRequest SVGScriptElement::InsertedInto(
67 ContainerNode& root_parent) {
68 SVGElement::InsertedInto(root_parent);
69 return kInsertionShouldCallDidNotifySubtreeInsertions;
70 }
71
DidNotifySubtreeInsertionsToDocument()72 void SVGScriptElement::DidNotifySubtreeInsertionsToDocument() {
73 loader_->DidNotifySubtreeInsertionsToDocument();
74
75 if (!loader_->IsParserInserted())
76 have_fired_load_ = true;
77 }
78
ChildrenChanged(const ChildrenChange & change)79 void SVGScriptElement::ChildrenChanged(const ChildrenChange& change) {
80 SVGElement::ChildrenChanged(change);
81 loader_->ChildrenChanged();
82 }
83
DidMoveToNewDocument(Document & old_document)84 void SVGScriptElement::DidMoveToNewDocument(Document& old_document) {
85 ScriptRunner::MovePendingScript(old_document, GetDocument(), loader_.Get());
86 SVGElement::DidMoveToNewDocument(old_document);
87 }
88
IsURLAttribute(const Attribute & attribute) const89 bool SVGScriptElement::IsURLAttribute(const Attribute& attribute) const {
90 return attribute.GetName() == AtomicString(SourceAttributeValue());
91 }
92
FinishParsingChildren()93 void SVGScriptElement::FinishParsingChildren() {
94 SVGElement::FinishParsingChildren();
95 have_fired_load_ = true;
96 DCHECK(!script_text_internal_slot_.length());
97 script_text_internal_slot_ = ParkableString(TextFromChildren().Impl());
98 }
99
HaveLoadedRequiredResources()100 bool SVGScriptElement::HaveLoadedRequiredResources() {
101 return have_fired_load_;
102 }
103
SourceAttributeValue() const104 String SVGScriptElement::SourceAttributeValue() const {
105 return LegacyHrefString(*this);
106 }
107
TypeAttributeValue() const108 String SVGScriptElement::TypeAttributeValue() const {
109 return getAttribute(svg_names::kTypeAttr).GetString();
110 }
111
ChildTextContent()112 String SVGScriptElement::ChildTextContent() {
113 return TextFromChildren();
114 }
115
ScriptTextInternalSlot() const116 String SVGScriptElement::ScriptTextInternalSlot() const {
117 return script_text_internal_slot_.ToString();
118 }
119
HasSourceAttribute() const120 bool SVGScriptElement::HasSourceAttribute() const {
121 return !LegacyHrefString(*this).IsNull();
122 }
123
IsConnected() const124 bool SVGScriptElement::IsConnected() const {
125 return Node::isConnected();
126 }
127
HasChildren() const128 bool SVGScriptElement::HasChildren() const {
129 return Node::hasChildren();
130 }
131
GetNonceForElement() const132 const AtomicString& SVGScriptElement::GetNonceForElement() const {
133 return ContentSecurityPolicy::IsNonceableElement(this) ? nonce()
134 : g_null_atom;
135 }
136
AllowInlineScriptForCSP(const AtomicString & nonce,const WTF::OrdinalNumber & context_line,const String & script_content)137 bool SVGScriptElement::AllowInlineScriptForCSP(
138 const AtomicString& nonce,
139 const WTF::OrdinalNumber& context_line,
140 const String& script_content) {
141 return GetExecutionContext()
142 ->GetContentSecurityPolicyForCurrentWorld()
143 ->AllowInline(ContentSecurityPolicy::InlineType::kScript, this,
144 script_content, nonce, GetDocument().Url(), context_line);
145 }
146
GetDocument() const147 Document& SVGScriptElement::GetDocument() const {
148 return Node::GetDocument();
149 }
150
GetExecutionContext() const151 ExecutionContext* SVGScriptElement::GetExecutionContext() const {
152 return Node::GetExecutionContext();
153 }
154
CloneWithoutAttributesAndChildren(Document & factory) const155 Element& SVGScriptElement::CloneWithoutAttributesAndChildren(
156 Document& factory) const {
157 CreateElementFlags flags =
158 CreateElementFlags::ByCloneNode().SetAlreadyStarted(
159 loader_->AlreadyStarted());
160 return *factory.CreateElement(TagQName(), flags, IsValue());
161 }
162
DispatchLoadEvent()163 void SVGScriptElement::DispatchLoadEvent() {
164 DispatchEvent(*Event::Create(event_type_names::kLoad));
165 have_fired_load_ = true;
166 }
167
DispatchErrorEvent()168 void SVGScriptElement::DispatchErrorEvent() {
169 DispatchEvent(*Event::Create(event_type_names::kError));
170 }
171
SetScriptElementForBinding(HTMLScriptElementOrSVGScriptElement & element)172 void SVGScriptElement::SetScriptElementForBinding(
173 HTMLScriptElementOrSVGScriptElement& element) {
174 if (!IsInV1ShadowTree())
175 element.SetSVGScriptElement(this);
176 }
177
GetScriptElementType()178 ScriptElementBase::Type SVGScriptElement::GetScriptElementType() {
179 return ScriptElementBase::Type::kSVGScriptElement;
180 }
181
182 #if DCHECK_IS_ON()
IsAnimatableAttribute(const QualifiedName & name) const183 bool SVGScriptElement::IsAnimatableAttribute(const QualifiedName& name) const {
184 if (name == svg_names::kTypeAttr || name == svg_names::kHrefAttr ||
185 name == xlink_names::kHrefAttr)
186 return false;
187 return SVGElement::IsAnimatableAttribute(name);
188 }
189 #endif
190
GetCheckedAttributeTypes() const191 const AttrNameToTrustedType& SVGScriptElement::GetCheckedAttributeTypes()
192 const {
193 DEFINE_STATIC_LOCAL(
194 AttrNameToTrustedType, attribute_map,
195 ({
196 {svg_names::kHrefAttr.LocalName(), SpecificTrustedType::kScriptURL},
197 }));
198 return attribute_map;
199 }
200
Trace(Visitor * visitor) const201 void SVGScriptElement::Trace(Visitor* visitor) const {
202 visitor->Trace(loader_);
203 SVGElement::Trace(visitor);
204 SVGURIReference::Trace(visitor);
205 ScriptElementBase::Trace(visitor);
206 }
207
208 } // namespace blink
209