Skip to content

Commit 54ca5d3

Browse files
committed
Implement trusted types integrations with DOM setAttribute APIs.
https://bugs.webkit.org/show_bug.cgi?id=270436. Reviewed by NOBODY (OOPS!). Implement the spec updates at whatwg/dom#1247. It also remove the some expectations in GTK as the results should be in line with the general expectation file. * LayoutTests/platform/gtk/TestExpectations: * Source/WebCore/dom/Element.cpp: (WebCore::getTrustedTypesCompliantAttributeValue): (WebCore::Element::setAttribute): (WebCore::Element::setElementsArrayAttribute): (WebCore::appendAttributes): (WebCore::Element::setAttributeNS): * Source/WebCore/dom/Element.h: * Source/WebCore/dom/Element.idl: * Source/WebCore/dom/TrustedType.cpp: (WebCore::stringToTrustedType): (WebCore::getAttributeTrustedType): * Source/WebCore/dom/TrustedType.h: * Source/WebCore/dom/TrustedTypePolicyFactory.cpp: (WebCore::TrustedTypePolicyFactory::getAttributeType const):
1 parent 2459e14 commit 54ca5d3

File tree

9 files changed

+105
-40
lines changed

9 files changed

+105
-40
lines changed

LayoutTests/platform/gtk/TestExpectations

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,14 +2337,6 @@ fast/mediastream/mediastreamtrack-video-frameRate-clone-decreasing.html [ Crash
23372337
# Trusted Types aren't implemented yet
23382338
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/trusted-types-reporting-check-report.html [ Failure Pass ]
23392339
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/block-string-assignment-to-attribute-via-attribute-node.html [ Failure Pass ]
2340-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/Element-setAttribute.html [ Failure ]
2341-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/WorkerGlobalScope-eval.html [ Failure ]
2342-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/WorkerGlobalScope-importScripts.html [ Failure ]
2343-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/block-string-assignment-to-Element-setAttribute.html [ Failure ]
2344-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/block-string-assignment-to-HTMLElement-generic.html [ Failure ]
2345-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/default-policy-report-only.html [ Failure ]
2346-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/default-policy.html [ Failure ]
2347-
webkit.org/b/266630 imported/w3c/web-platform-tests/trusted-types/worker-constructor.https.html [ Failure ]
23482340

23492341
# Flaky tests on Aug-2023
23502342
webkit.org/b/261024 animations/change-completed-animation-transform.html [ ImageOnlyFailure Pass ]

Source/WebCore/dom/Element.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
#include "StyleTreeResolver.h"
146146
#include "TextIterator.h"
147147
#include "TouchAction.h"
148+
#include "TrustedType.h"
148149
#include "TypedElementDescendantIteratorInlines.h"
149150
#include "VisibilityAdjustment.h"
150151
#include "VoidCallback.h"
@@ -2000,7 +2001,31 @@ ExceptionOr<bool> Element::toggleAttribute(const AtomString& qualifiedName, std:
20002001
return true;
20012002
}
20022003

2003-
ExceptionOr<void> Element::setAttribute(const AtomString& qualifiedName, const AtomString& value)
2004+
static ExceptionOr<String> getTrustedTypesCompliantAttributeValue(const String& attributeType, const TrustedTypeOrString& value, Element* element, String sink)
2005+
{
2006+
auto stringValueHolder = WTF::switchOn(value,
2007+
[&](const String& str) -> ExceptionOr<String> {
2008+
if (attributeType.isNull())
2009+
return String(str);
2010+
return trustedTypeCompliantString(stringToTrustedType(attributeType), *(element->document().scriptExecutionContext()), str, sink);
2011+
},
2012+
[](const RefPtr<TrustedHTML>& trustedHTML) -> ExceptionOr<String> {
2013+
return trustedHTML->toString();
2014+
},
2015+
[](const RefPtr<TrustedScript>& trustedScript) -> ExceptionOr<String> {
2016+
return trustedScript->toString();
2017+
},
2018+
[](const RefPtr<TrustedScriptURL>& trustedScriptURL) -> ExceptionOr<String> {
2019+
return trustedScriptURL->toString();
2020+
}
2021+
);
2022+
if (stringValueHolder.hasException())
2023+
return stringValueHolder.releaseException();
2024+
2025+
return stringValueHolder.releaseReturnValue();
2026+
}
2027+
2028+
ExceptionOr<void> Element::setAttribute(const AtomString& qualifiedName, const TrustedTypeOrString& value)
20042029
{
20052030
if (!Document::isValidName(qualifiedName))
20062031
return Exception { ExceptionCode::InvalidCharacterError, makeString("Invalid qualified name: '", qualifiedName, "'") };
@@ -2009,8 +2034,18 @@ ExceptionOr<void> Element::setAttribute(const AtomString& qualifiedName, const A
20092034
auto caseAdjustedQualifiedName = shouldIgnoreAttributeCase(*this) ? qualifiedName.convertToASCIILowercase() : qualifiedName;
20102035
unsigned index = elementData() ? elementData()->findAttributeIndexByName(caseAdjustedQualifiedName, false) : ElementData::attributeNotFound;
20112036
auto name = index != ElementData::attributeNotFound ? attributeAt(index).name() : QualifiedName { nullAtom(), caseAdjustedQualifiedName, nullAtom() };
2012-
setAttributeInternal(index, name, value, InSynchronizationOfLazyAttribute::No);
2037+
if (!document().scriptExecutionContext()->settingsValues().trustedTypesEnabled)
2038+
setAttributeInternal(index, name, std::get<AtomString>(value), InSynchronizationOfLazyAttribute::No);
2039+
else {
2040+
auto sink = nullString();
2041+
String attributeType = getTrustedTypeForAttribute(name.localName(), getAttribute(name), ""_s, ""_s);
2042+
auto attributeValue = getTrustedTypesCompliantAttributeValue(attributeType, value, this, "Element setAttribute"_s);
20132043

2044+
if (attributeValue.hasException())
2045+
return attributeValue.releaseException();
2046+
2047+
setAttributeInternal(index, name, AtomString(attributeValue.releaseReturnValue()), InSynchronizationOfLazyAttribute::No);
2048+
}
20142049
return { };
20152050
}
20162051

@@ -2314,7 +2349,7 @@ void Element::setElementsArrayAttribute(const QualifiedName& attributeName, std:
23142349

23152350
auto newElements = copyToVectorOf<WeakPtr<Element, WeakPtrImplWithEventTargetData>>(*elements);
23162351
explicitlySetAttrElementsMap().set(attributeName, WTFMove(newElements));
2317-
2352+
23182353
if (CheckedPtr cache = document().existingAXObjectCache()) {
23192354
for (auto element : elements.value()) {
23202355
// FIXME: Should this pass `element` instead of `*this`?
@@ -3227,7 +3262,7 @@ static void appendAttributes(StringBuilder& builder, const Element& element)
32273262
classNamesToDump = maxNumClassNames;
32283263
addEllipsis = true;
32293264
}
3230-
3265+
32313266
for (size_t i = 0; i < classNamesToDump; ++i) {
32323267
if (i > 0)
32333268
builder.append(' ');
@@ -3395,12 +3430,23 @@ ExceptionOr<QualifiedName> Element::parseAttributeName(const AtomString& namespa
33953430
return parsedAttributeName;
33963431
}
33973432

3398-
ExceptionOr<void> Element::setAttributeNS(const AtomString& namespaceURI, const AtomString& qualifiedName, const AtomString& value)
3433+
ExceptionOr<void> Element::setAttributeNS(const AtomString& namespaceURI, const AtomString& qualifiedName, const TrustedTypeOrString& value)
33993434
{
34003435
auto result = parseAttributeName(namespaceURI, qualifiedName);
34013436
if (result.hasException())
34023437
return result.releaseException();
3403-
setAttribute(result.releaseReturnValue(), value);
3438+
if (!document().scriptExecutionContext()->settingsValues().trustedTypesEnabled)
3439+
setAttribute(result.releaseReturnValue(), std::get<AtomString>(value));
3440+
else {
3441+
String attributeType = getTrustedTypeForAttribute(qualifiedName, getAttribute(qualifiedName), ""_s, namespaceURI);
3442+
auto attributeValue = getTrustedTypesCompliantAttributeValue(attributeType, value, this, "Element setAttributeNS"_s);
3443+
3444+
if (attributeValue.hasException())
3445+
return attributeValue.releaseException();
3446+
3447+
setAttribute(result.releaseReturnValue(), AtomString(attributeValue.releaseReturnValue()));
3448+
}
3449+
34043450
return { };
34053451
}
34063452

Source/WebCore/dom/Element.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535
#include "ScrollTypes.h"
3636
#include "ShadowRootMode.h"
3737
#include "SimulatedClickOptions.h"
38+
#include "TrustedHTML.h"
39+
#include "TrustedScript.h"
40+
#include "TrustedScriptURL.h"
3841
#include "WebAnimationTypes.h"
3942
#include <JavaScriptCore/Forward.h>
4043

@@ -119,6 +122,7 @@ struct ShadowRootInit;
119122

120123
using ElementName = NodeName;
121124
using ExplicitlySetAttrElementsMap = HashMap<QualifiedName, Vector<WeakPtr<Element, WeakPtrImplWithEventTargetData>>>;
125+
using TrustedTypeOrString = std::variant<RefPtr<TrustedHTML>, RefPtr<TrustedScript>, RefPtr<TrustedScriptURL>, AtomString>;
122126

123127
// https://drafts.csswg.org/css-contain/#relevant-to-the-user
124128
enum class ContentRelevancy : uint8_t {
@@ -190,9 +194,9 @@ class Element : public ContainerNode {
190194
AtomString getAttributeForBindings(const AtomString& qualifiedName, ResolveURLs = ResolveURLs::NoExcludingURLsForPrivacy) const;
191195
inline AtomString getAttributeNSForBindings(const AtomString& namespaceURI, const AtomString& localName, ResolveURLs = ResolveURLs::NoExcludingURLsForPrivacy) const;
192196

193-
WEBCORE_EXPORT ExceptionOr<void> setAttribute(const AtomString& qualifiedName, const AtomString& value);
197+
WEBCORE_EXPORT ExceptionOr<void> setAttribute(const AtomString& qualifiedName, const TrustedTypeOrString& value);
194198
static ExceptionOr<QualifiedName> parseAttributeName(const AtomString& namespaceURI, const AtomString& qualifiedName);
195-
WEBCORE_EXPORT ExceptionOr<void> setAttributeNS(const AtomString& namespaceURI, const AtomString& qualifiedName, const AtomString& value);
199+
WEBCORE_EXPORT ExceptionOr<void> setAttributeNS(const AtomString& namespaceURI, const AtomString& qualifiedName, const TrustedTypeOrString& value);
196200

197201
ExceptionOr<bool> toggleAttribute(const AtomString& qualifiedName, std::optional<bool> force);
198202

Source/WebCore/dom/Element.idl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@
4242
sequence<DOMString> getAttributeNames();
4343
[DOMJIT=ReadDOM, ImplementedAs=getAttributeForBindings] DOMString? getAttribute([AtomString] DOMString qualifiedName);
4444
[ImplementedAs=getAttributeNSForBindings] DOMString? getAttributeNS([AtomString] DOMString? namespaceURI, [AtomString] DOMString localName);
45-
[CEReactions=Needed] undefined setAttribute([AtomString] DOMString qualifiedName, [AtomString] DOMString value);
46-
[CEReactions=Needed] undefined setAttributeNS([AtomString] DOMString? namespaceURI, [AtomString] DOMString qualifiedName, [AtomString] DOMString value);
45+
[CEReactions=Needed] undefined setAttribute([AtomString] DOMString qualifiedName, (TrustedType or [AtomString] DOMString) value);
46+
[CEReactions=Needed] undefined setAttributeNS([AtomString] DOMString? namespaceURI, [AtomString] DOMString qualifiedName, (TrustedType or [AtomString] DOMString) value);
4747
[CEReactions=Needed, ImplementedAs=removeAttributeForBindings] undefined removeAttribute([AtomString] DOMString qualifiedName);
4848
[CEReactions=Needed, ImplementedAs=removeAttributeNSForBindings] undefined removeAttributeNS([AtomString] DOMString? namespaceURI, [AtomString] DOMString localName);
4949
[CEReactions=Needed] boolean toggleAttribute([AtomString] DOMString qualifiedName, optional boolean force);
@@ -106,3 +106,5 @@ Element includes NonDocumentTypeChildNode;
106106
Element includes ParentNode;
107107
Element includes Slotable;
108108
Element includes InnerHTML;
109+
110+
typedef (TrustedHTML or TrustedScript or TrustedScriptURL) TrustedType;

Source/WebCore/dom/TrustedScript.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
namespace WebCore {
3131

32-
class TrustedScript final : public ScriptWrappable, public RefCounted<TrustedScript> {
32+
class WEBCORE_EXPORT TrustedScript final : public ScriptWrappable, public RefCounted<TrustedScript> {
3333
WTF_MAKE_ISO_ALLOCATED(TrustedScript);
3434
public:
3535
static Ref<TrustedScript> create(const String& data);

Source/WebCore/dom/TrustedScriptURL.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
namespace WebCore {
3333

34-
class TrustedScriptURL : public ScriptWrappable, public RefCounted<TrustedScriptURL> {
34+
class WEBCORE_EXPORT TrustedScriptURL : public ScriptWrappable, public RefCounted<TrustedScriptURL> {
3535
WTF_MAKE_ISO_ALLOCATED(TrustedScriptURL);
3636
public:
3737
static Ref<TrustedScriptURL> create(const String& data);

Source/WebCore/dom/TrustedType.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "TrustedTypePolicyFactory.h"
3838
#include "WindowOrWorkerGlobalScopeTrustedTypes.h"
3939
#include "WorkerGlobalScope.h"
40+
#include "XLinkNames.h"
4041
#include <JavaScriptCore/HeapInlines.h>
4142
#include <JavaScriptCore/JSCInlines.h>
4243
#include <JavaScriptCore/JSCJSValueInlines.h>
@@ -84,6 +85,19 @@ ASCIILiteral trustedTypeToString(TrustedType trustedType)
8485
return { };
8586
}
8687

88+
TrustedType stringToTrustedType(String str)
89+
{
90+
if (str == "TrustedHTML"_s)
91+
return TrustedType::TrustedHTML;
92+
if (str == "TrustedScript"_s)
93+
return TrustedType::TrustedScript;
94+
if (str == "TrustedScriptURL"_s)
95+
return TrustedType::TrustedScriptURL;
96+
97+
ASSERT_NOT_REACHED();
98+
return { };
99+
}
100+
87101
ASCIILiteral trustedTypeToCallbackName(TrustedType trustedType)
88102
{
89103
switch (trustedType) {
@@ -173,6 +187,30 @@ ExceptionOr<String> trustedTypeCompliantString(TrustedType expectedType, ScriptE
173187
return stringValue;
174188
}
175189

190+
String getTrustedTypeForAttribute(const String& tagName, const String& attributeParameter, const String& elementNamespace, const String& attributeNamespace)
191+
{
192+
auto localName = tagName.convertToASCIILowercase();
193+
auto attributeName = attributeParameter.convertToASCIILowercase();
194+
195+
if (attributeName.startsWith("on"_s))
196+
return trustedTypeToString(TrustedType::TrustedScript);
197+
198+
AtomString elementNS = elementNamespace.isEmpty() ? HTMLNames::xhtmlNamespaceURI : AtomString(elementNamespace);
199+
AtomString attributeNS = attributeNamespace.isEmpty() ? nullAtom() : AtomString(attributeNamespace);
200+
201+
QualifiedName element(nullAtom(), AtomString(localName), elementNS);
202+
QualifiedName attribute(nullAtom(), AtomString(attributeName), attributeNS);
203+
204+
if (element.matches(HTMLNames::iframeTag) && attribute.matches(HTMLNames::srcdocAttr))
205+
return trustedTypeToString(TrustedType::TrustedHTML);
206+
if (element.matches(HTMLNames::scriptTag) && attribute.matches(HTMLNames::srcAttr))
207+
return trustedTypeToString(TrustedType::TrustedScriptURL);
208+
if (element.matches(SVGNames::scriptTag) && (attribute.matches(SVGNames::hrefAttr) || attribute.matches(XLinkNames::hrefAttr)))
209+
return trustedTypeToString(TrustedType::TrustedScriptURL);
210+
211+
return nullString();
212+
}
213+
176214
// https://w3c.github.io/trusted-types/dist/spec/#require-trusted-types-for-pre-navigation-check
177215
ExceptionOr<String> requireTrustedTypesForPreNavigationCheckPasses(ScriptExecutionContext& scriptExecutionContext, const String& urlString)
178216
{

Source/WebCore/dom/TrustedType.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ enum class TrustedType : int8_t {
4545
};
4646

4747
ASCIILiteral trustedTypeToString(TrustedType);
48+
TrustedType stringToTrustedType(String);
4849
ASCIILiteral trustedTypeToCallbackName(TrustedType);
4950

5051
WEBCORE_EXPORT std::variant<std::monostate, Exception, Ref<TrustedHTML>, Ref<TrustedScript>, Ref<TrustedScriptURL>> processValueWithDefaultPolicy(ScriptExecutionContext&, TrustedType, const String& input, const String& sink);
@@ -55,4 +56,5 @@ WEBCORE_EXPORT ExceptionOr<String> requireTrustedTypesForPreNavigationCheckPasse
5556

5657
ExceptionOr<RefPtr<Text>> processNodeOrStringAsTrustedType(Ref<Document>, RefPtr<Node> parent, std::variant<RefPtr<Node>, String, RefPtr<TrustedScript>>);
5758

59+
WEBCORE_EXPORT String getTrustedTypeForAttribute(const String& tagName, const String& attributeParameter, const String& elementNamespace, const String& attributeNamespace);
5860
} // namespace WebCore

Source/WebCore/dom/TrustedTypePolicyFactory.cpp

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -108,26 +108,7 @@ Ref<TrustedScript> TrustedTypePolicyFactory::emptyScript() const
108108

109109
String TrustedTypePolicyFactory::getAttributeType(const String& tagName, const String& attributeParameter, const String& elementNamespace, const String& attributeNamespace) const
110110
{
111-
auto localName = tagName.convertToASCIILowercase();
112-
auto attributeName = attributeParameter.convertToASCIILowercase();
113-
114-
if (attributeName.startsWith("on"_s))
115-
return trustedTypeToString(TrustedType::TrustedScript);
116-
117-
AtomString elementNS = elementNamespace.isEmpty() ? HTMLNames::xhtmlNamespaceURI : AtomString(elementNamespace);
118-
AtomString attributeNS = attributeNamespace.isEmpty() ? nullAtom() : AtomString(attributeNamespace);
119-
120-
QualifiedName element(nullAtom(), AtomString(localName), elementNS);
121-
QualifiedName attribute(nullAtom(), AtomString(attributeName), attributeNS);
122-
123-
if (element.matches(HTMLNames::iframeTag) && attribute.matches(HTMLNames::srcdocAttr))
124-
return trustedTypeToString(TrustedType::TrustedHTML);
125-
if (element.matches(HTMLNames::scriptTag) && attribute.matches(HTMLNames::srcAttr))
126-
return trustedTypeToString(TrustedType::TrustedScriptURL);
127-
if (element.matches(SVGNames::scriptTag) && (attribute.matches(SVGNames::hrefAttr) || attribute.matches(XLinkNames::hrefAttr)))
128-
return trustedTypeToString(TrustedType::TrustedScriptURL);
129-
130-
return nullString();
111+
return getTrustedTypeForAttribute(tagName, attributeParameter, elementNamespace, attributeNamespace);
131112
}
132113

133114
String TrustedTypePolicyFactory::getPropertyType(const String& tagName, const String& property, const String& elementNamespace) const

0 commit comments

Comments
 (0)