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