Skip to content

Commit

Permalink
Implement trusted types integration with execCommand
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=267690

Reviewed by Youenn Fablet and Ryosuke Niwa.

Call trustedTypeCompliantString from within document execCommand when command is insertHTML.

* LayoutTests/imported/w3c/web-platform-tests/trusted-types/block-Document-execCommand-expected.txt:
* Source/WebCore/dom/Document+HTML.idl:
* Source/WebCore/dom/Document.cpp:
(WebCore::Document::execCommand):
* Source/WebCore/dom/Document.h:
* Source/WebCore/dom/TrustedHTML.h:

Canonical link: https://commits.webkit.org/275667@main
  • Loading branch information
lukewarlow committed Mar 5, 2024
1 parent 6ec42b4 commit 9fc59f1
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
CONSOLE MESSAGE: This requires a TrustedHTML value else it violates the following Content Security Policy directive: "require-trusted-types-for 'script'"

FAIL Document.execCommand("insertHTML") throws. assert_throws_js: function "_ => document.execCommand(command, false, "<em>Hello World</em>")" did not throw
PASS Document.execCommand("insertHTML") throws.
PASS Document.execCommand("insertHTML") works with a TrustedHTML argument.
PASS Document.execCommand("paste") works as usual."
PASS Document.execCommand("paste") works with a TrustedHTML argument.
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/Document+HTML.idl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ partial interface Document {
[ImplementedAs=windowProxy] readonly attribute WindowProxy? defaultView;
boolean hasFocus();
[CEReactions=Needed] attribute DOMString designMode;
[CEReactions=Needed] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
[CEReactions=Needed] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional (DOMString or TrustedHTML) value = "");
boolean queryCommandEnabled(DOMString commandId);
boolean queryCommandIndeterm(DOMString commandId);
boolean queryCommandState(DOMString commandId);
Expand Down
19 changes: 17 additions & 2 deletions Source/WebCore/dom/Document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@
#include "TouchAction.h"
#include "TransformSource.h"
#include "TreeWalker.h"
#include "TrustedType.h"
#include "TypedElementDescendantIteratorInlines.h"
#include "UndoManager.h"
#include "UserGestureIndicator.h"
Expand Down Expand Up @@ -6895,13 +6896,27 @@ static Editor::Command command(Document* document, const String& commandName, bo
userInterface ? EditorCommandSource::DOMWithUserInterface : EditorCommandSource::DOM);
}

ExceptionOr<bool> Document::execCommand(const String& commandName, bool userInterface, const String& value)
ExceptionOr<bool> Document::execCommand(const String& commandName, bool userInterface, const std::variant<String, RefPtr<TrustedHTML>>& value)
{
if (UNLIKELY(!isHTMLDocument() && !isXHTMLDocument()))
return Exception { ExceptionCode::InvalidStateError, "execCommand is only supported on HTML documents."_s };

auto stringValueHolder = WTF::switchOn(value,
[&commandName, this](const String& str) -> ExceptionOr<String> {
if (commandName != "insertHTML"_s)
return String(str);
return trustedTypeCompliantString(TrustedType::TrustedHTML, *scriptExecutionContext(), str, "Document execCommand"_s);
},
[](const RefPtr<TrustedHTML>& trustedHtml) -> ExceptionOr<String> {
return trustedHtml->toString();
}
);

if (stringValueHolder.hasException())
return stringValueHolder.releaseException();

EventQueueScope eventQueueScope;
return command(this, commandName, userInterface).execute(value);
return command(this, commandName, userInterface).execute(stringValueHolder.releaseReturnValue());
}

ExceptionOr<bool> Document::queryCommandEnabled(const String& commandName)
Expand Down
3 changes: 2 additions & 1 deletion Source/WebCore/dom/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "Supplementable.h"
#include "Timer.h"
#include "TreeScope.h"
#include "TrustedHTML.h"
#include "URLKeepingBlobAlive.h"
#include "UserActionElementSet.h"
#include "ViewportArguments.h"
Expand Down Expand Up @@ -1197,7 +1198,7 @@ class Document
inline CheckedRef<DocumentMarkerController> checkedMarkers(); // Defined in DocumentInlines.h.
inline CheckedRef<const DocumentMarkerController> checkedMarkers() const; // Defined in DocumentInlines.h.

WEBCORE_EXPORT ExceptionOr<bool> execCommand(const String& command, bool userInterface = false, const String& value = String());
WEBCORE_EXPORT ExceptionOr<bool> execCommand(const String& command, bool userInterface = false, const std::variant<String, RefPtr<TrustedHTML>>& value = String());
WEBCORE_EXPORT ExceptionOr<bool> queryCommandEnabled(const String& command);
WEBCORE_EXPORT ExceptionOr<bool> queryCommandIndeterm(const String& command);
WEBCORE_EXPORT ExceptionOr<bool> queryCommandState(const String& command);
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/dom/TrustedHTML.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

namespace WebCore {

class TrustedHTML : public ScriptWrappable, public RefCounted<TrustedHTML> {
class WEBCORE_EXPORT TrustedHTML : public ScriptWrappable, public RefCounted<TrustedHTML> {
WTF_MAKE_ISO_ALLOCATED(TrustedHTML);
public:
static Ref<TrustedHTML> create(const String& data);
Expand Down

0 comments on commit 9fc59f1

Please sign in to comment.