Skip to content

Commit

Permalink
LibWeb: Disallow editing API calls on non-HTML documents
Browse files Browse the repository at this point in the history
This is not directly mentioned in the Editing API spec, but all major
browsers do this and there is a WPT for this behavior.
  • Loading branch information
tcl3 committed Jan 21, 2025
1 parent d967f56 commit 9fdeae9
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 8 deletions.
7 changes: 7 additions & 0 deletions Libraries/LibWeb/DOM/Document.h
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,13 @@ class Document
bool query_command_supported(FlyString const& command);
String query_command_value(FlyString const& command);

WebIDL::ExceptionOr<bool> exec_command_binding(FlyString const& command, bool show_ui, String const& value);
WebIDL::ExceptionOr<bool> query_command_enabled_binding(FlyString const& command);
WebIDL::ExceptionOr<bool> query_command_indeterm_binding(FlyString const& command);
WebIDL::ExceptionOr<bool> query_command_state_binding(FlyString const& command);
WebIDL::ExceptionOr<bool> query_command_supported_binding(FlyString const& command);
WebIDL::ExceptionOr<String> query_command_value_binding(FlyString const& command);

// https://w3c.github.io/selection-api/#dfn-has-scheduled-selectionchange-event
bool has_scheduled_selectionchange_event() const { return m_has_scheduled_selectionchange_event; }
void set_scheduled_selectionchange_event(bool value) { m_has_scheduled_selectionchange_event = value; }
Expand Down
12 changes: 6 additions & 6 deletions Libraries/LibWeb/DOM/Document.idl
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@ interface Document : Node {

// https://w3c.github.io/editing/docs/execCommand/
// FIXME: [CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional (TrustedHTML or DOMString) value = "");
[CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
boolean queryCommandEnabled(DOMString commandId);
boolean queryCommandIndeterm(DOMString commandId);
boolean queryCommandState(DOMString commandId);
boolean queryCommandSupported(DOMString commandId);
DOMString queryCommandValue(DOMString commandId);
[CEReactions, ImplementedAs=exec_command_binding] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
[ImplementedAs=query_command_enabled_binding] boolean queryCommandEnabled(DOMString commandId);
[ImplementedAs=query_command_indeterm_binding] boolean queryCommandIndeterm(DOMString commandId);
[ImplementedAs=query_command_state_binding] boolean queryCommandState(DOMString commandId);
[ImplementedAs=query_command_supported_binding] boolean queryCommandSupported(DOMString commandId);
[ImplementedAs=query_command_value_binding] DOMString queryCommandValue(DOMString commandId);

// special event handler IDL attributes that only apply to Document objects
[LegacyLenientThis] attribute EventHandler onreadystatechange;
Expand Down
54 changes: 54 additions & 0 deletions Libraries/LibWeb/Editing/ExecCommand.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@

namespace Web::DOM {

WebIDL::ExceptionOr<bool> Document::exec_command_binding(FlyString const& command, bool show_ui, String const& value)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "execCommand is only supported on HTML documents"_string);

return exec_command(command, show_ui, value);
}

// https://w3c.github.io/editing/docs/execCommand/#execcommand()
bool Document::exec_command(FlyString const& command, [[maybe_unused]] bool show_ui, String const& value)
{
Expand Down Expand Up @@ -98,6 +107,15 @@ bool Document::exec_command(FlyString const& command, [[maybe_unused]] bool show
return true;
}

WebIDL::ExceptionOr<bool> Document::query_command_enabled_binding(FlyString const& command)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "queryCommandEnabled is only supported on HTML documents"_string);

return query_command_enabled(command);
}

// https://w3c.github.io/editing/docs/execCommand/#querycommandenabled()
bool Document::query_command_enabled(FlyString const& command)
{
Expand Down Expand Up @@ -178,6 +196,15 @@ bool Document::query_command_enabled(FlyString const& command)
return true;
}

WebIDL::ExceptionOr<bool> Document::query_command_indeterm_binding(FlyString const& command)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "queryCommandIndeterm is only supported on HTML documents"_string);

return query_command_indeterm(command);
}

// https://w3c.github.io/editing/docs/execCommand/#querycommandindeterm()
bool Document::query_command_indeterm(FlyString const& command)
{
Expand Down Expand Up @@ -250,6 +277,15 @@ bool Document::query_command_indeterm(FlyString const& command)
return command_definition.indeterminate(*this);
}

WebIDL::ExceptionOr<bool> Document::query_command_state_binding(FlyString const& command)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "queryCommandState is only supported on HTML documents"_string);

return query_command_state(command);
}

// https://w3c.github.io/editing/docs/execCommand/#querycommandstate()
bool Document::query_command_state(FlyString const& command)
{
Expand Down Expand Up @@ -292,6 +328,15 @@ bool Document::query_command_state(FlyString const& command)
return command_definition.state(*this);
}

WebIDL::ExceptionOr<bool> Document::query_command_supported_binding(FlyString const& command)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "queryCommandSupported is only supported on HTML documents"_string);

return query_command_supported(command);
}

// https://w3c.github.io/editing/docs/execCommand/#querycommandsupported()
bool Document::query_command_supported(FlyString const& command)
{
Expand All @@ -301,6 +346,15 @@ bool Document::query_command_supported(FlyString const& command)
return Editing::find_command_definition(command).has_value();
}

WebIDL::ExceptionOr<String> Document::query_command_value_binding(FlyString const& command)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
return WebIDL::InvalidStateError::create(realm(), "queryCommandValue is only supported on HTML documents"_string);

return query_command_value(command);
}

// https://w3c.github.io/editing/docs/execCommand/#querycommandvalue()
String Document::query_command_value(FlyString const& command)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ DIV 0 - DIV 0
BODY 0 - BODY 5
true
false
false
Did not crash!
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Harness status: OK

Found 1 tests

1 Pass
Pass editing APIs on an XML document should be disabled
1 change: 0 additions & 1 deletion Tests/LibWeb/Text/input/Editing/execCommand-selectAll.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
// Report whether command is enabled and make sure it does not crash
const documents = [
document,
new Document(),
document.implementation.createHTMLDocument(),
];
for (const doc of documents) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!doctype html>
<meta charset=utf-8>
<title>Non-HTML document tests</title>
<script src=../../resources/testharness.js></script>
<script src=../../resources/testharnessreport.js></script>
<script>

test(function() {
let xmldoc =
document.implementation.createDocument("http://www.w3.org/1999/xlink",
"html", null);
for (let f of [
() => xmldoc.execCommand("bold"),
() => xmldoc.queryCommandEnabled("bold"),
() => xmldoc.queryCommandIndeterm("bold"),
() => xmldoc.queryCommandState("bold"),
() => xmldoc.queryCommandSupported("bold"),
() => xmldoc.queryCommandValue("bold"),
]) {
assert_throws_dom("InvalidStateError", f);
}
}, "editing APIs on an XML document should be disabled");

</script>

0 comments on commit 9fdeae9

Please sign in to comment.