LibWeb: Amend Document interface to make it compatible with TrustedTypes

This commit is contained in:
Tete17 2025-08-08 17:34:23 +02:00 committed by Luke Wilde
parent 2fa84f1683
commit 1368744d33
4 changed files with 50 additions and 25 deletions

View File

@ -165,6 +165,8 @@
#include <LibWeb/SVG/SVGStyleElement.h> #include <LibWeb/SVG/SVGStyleElement.h>
#include <LibWeb/SVG/SVGTitleElement.h> #include <LibWeb/SVG/SVGTitleElement.h>
#include <LibWeb/Selection/Selection.h> #include <LibWeb/Selection/Selection.h>
#include <LibWeb/TrustedTypes/RequireTrustedTypesForDirective.h>
#include <LibWeb/TrustedTypes/TrustedTypePolicy.h>
#include <LibWeb/UIEvents/CompositionEvent.h> #include <LibWeb/UIEvents/CompositionEvent.h>
#include <LibWeb/UIEvents/EventNames.h> #include <LibWeb/UIEvents/EventNames.h>
#include <LibWeb/UIEvents/FocusEvent.h> #include <LibWeb/UIEvents/FocusEvent.h>
@ -644,41 +646,56 @@ GC::Ptr<Selection::Selection> Document::get_selection() const
} }
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-write // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-write
WebIDL::ExceptionOr<void> Document::write(Vector<String> const& text) WebIDL::ExceptionOr<void> Document::write(Vector<TrustedTypes::TrustedHTMLOrString> const& text)
{ {
// The document.write(...text) method steps are to run the document write steps with this, text, false, and "Document write". // The document.write(...text) method steps are to run the document write steps with this, text, false, and "Document write".
return run_the_document_write_steps(text, AddLineFeed::No, TrustedTypes::InjectionSink::Documentwrite); return run_the_document_write_steps(text, AddLineFeed::No, TrustedTypes::InjectionSink::Documentwrite);
} }
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-writeln // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-writeln
WebIDL::ExceptionOr<void> Document::writeln(Vector<String> const& text) WebIDL::ExceptionOr<void> Document::writeln(Vector<TrustedTypes::TrustedHTMLOrString> const& text)
{ {
// The document.writeln(...text) method steps are to run the document write steps with this, text, true, and "Document writeln". // The document.writeln(...text) method steps are to run the document write steps with this, text, true, and "Document writeln".
return run_the_document_write_steps(text, AddLineFeed::Yes, TrustedTypes::InjectionSink::Documentwriteln); return run_the_document_write_steps(text, AddLineFeed::Yes, TrustedTypes::InjectionSink::Documentwriteln);
} }
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document-write-steps
WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(Vector<String> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink) WebIDL::ExceptionOr<void> Document::run_the_document_write_steps(Vector<TrustedTypes::TrustedHTMLOrString> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink)
{ {
// 1. Let string be the empty string. // 1. Let string be the empty string.
StringBuilder string; StringBuilder string;
// 2. Let isTrusted be false if text contains a string; otherwise true. // 2. Let isTrusted be false if text contains a string; otherwise true.
// FIXME: We currently only accept strings. Revisit this once we support the TrustedHTML type.
auto is_trusted = true; auto is_trusted = true;
for (auto const& value : text) {
if (value.has<Utf16String>()) {
is_trusted = false;
break;
}
}
// 3. For each value of text: // 3. For each value of text:
for (auto const& value : text) { for (auto const& value : text) {
// FIXME: 1. If value is a TrustedHTML object, then append value's associated data to string. string.append(value.visit(
// 1. If value is a TrustedHTML object, then append value's associated data to string.
// 2. Otherwise, append value to string. [](GC::Root<TrustedTypes::TrustedHTML> const& value) { return value->to_string(); },
string.append(value); // 2. Otherwise, append value to string.
[](Utf16String const& value) { return value; })
.to_utf8_but_should_be_ported_to_utf16());
} }
// FIXME: 4. If isTrusted is false, set string to the result of invoking the Get Trusted Type compliant string algorithm // 4. If isTrusted is false, set string to the result of invoking the Get Trusted Type compliant string algorithm
// with TrustedHTML, this's relevant global object, string, sink, and "script". // with TrustedHTML, this's relevant global object, string, sink, and "script".
(void)is_trusted; if (!is_trusted) {
(void)sink; auto const new_string = TRY(TrustedTypes::get_trusted_type_compliant_string(
TrustedTypes::TrustedTypeName::TrustedHTML,
relevant_global_object(*this),
Utf16String::from_utf8(MUST(string.to_string())),
sink,
TrustedTypes::Script.to_string()));
string.clear();
string.append(new_string.to_utf8_but_should_be_ported_to_utf16());
}
// 5. If lineFeed is true, append U+000A LINE FEED to string. // 5. If lineFeed is true, append U+000A LINE FEED to string.
if (line_feed == AddLineFeed::Yes) if (line_feed == AddLineFeed::Yes)
@ -6345,10 +6362,19 @@ void Document::parse_html_from_a_string(StringView html)
} }
// https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsehtmlunsafe // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-parsehtmlunsafe
GC::Ref<Document> Document::parse_html_unsafe(JS::VM& vm, StringView html) WebIDL::ExceptionOr<GC::Root<DOM::Document>> Document::parse_html_unsafe(JS::VM& vm, TrustedTypes::TrustedHTMLOrString const& html)
{ {
auto& realm = *vm.current_realm(); auto& realm = *vm.current_realm();
// FIXME: 1. Let compliantHTML to the result of invoking the Get Trusted Type compliant string algorithm with TrustedHTML, this's relevant global object, html, "Document parseHTMLUnsafe", and "script".
// FIXME: update description once https://github.com/whatwg/html/issues/11778 gets solved
// 1. Let compliantHTML to the result of invoking the Get Trusted Type compliant string algorithm with
// TrustedHTML, this's relevant global object, html, "Document parseHTMLUnsafe", and "script".
auto const compliant_html = TRY(TrustedTypes::get_trusted_type_compliant_string(
TrustedTypes::TrustedTypeName::TrustedHTML,
HTML::current_principal_global_object(),
html,
TrustedTypes::InjectionSink::DocumentparseHTMLUnsafe,
TrustedTypes::Script.to_string()));
// 2. Let document be a new Document, whose content type is "text/html". // 2. Let document be a new Document, whose content type is "text/html".
auto document = Document::create_for_fragment_parsing(realm); auto document = Document::create_for_fragment_parsing(realm);
@ -6357,8 +6383,8 @@ GC::Ref<Document> Document::parse_html_unsafe(JS::VM& vm, StringView html)
// 3. Set document's allow declarative shadow roots to true. // 3. Set document's allow declarative shadow roots to true.
document->set_allow_declarative_shadow_roots(true); document->set_allow_declarative_shadow_roots(true);
// 4. Parse HTML from a string given document and compliantHTML. // FIXME: Use compliantHTML. // 4. Parse HTML from a string given document and compliantHTML.
document->parse_html_from_a_string(html); document->parse_html_from_a_string(compliant_html.to_utf8_but_should_be_ported_to_utf16());
// AD-HOC: Setting the origin to match that of the associated document matches the behavior of existing browsers. // AD-HOC: Setting the origin to match that of the associated document matches the behavior of existing browsers.
auto& associated_document = as<HTML::Window>(realm.global_object()).associated_document(); auto& associated_document = as<HTML::Window>(realm.global_object()).associated_document();

View File

@ -472,8 +472,8 @@ public:
void set_window(HTML::Window&); void set_window(HTML::Window&);
WebIDL::ExceptionOr<void> write(Vector<String> const& strings); WebIDL::ExceptionOr<void> write(Vector<TrustedTypes::TrustedHTMLOrString> const& text);
WebIDL::ExceptionOr<void> writeln(Vector<String> const& strings); WebIDL::ExceptionOr<void> writeln(Vector<TrustedTypes::TrustedHTMLOrString> const& text);
WebIDL::ExceptionOr<Document*> open(Optional<String> const& = {}, Optional<String> const& = {}); WebIDL::ExceptionOr<Document*> open(Optional<String> const& = {}, Optional<String> const& = {});
WebIDL::ExceptionOr<GC::Ptr<HTML::WindowProxy>> open(StringView url, StringView name, StringView features); WebIDL::ExceptionOr<GC::Ptr<HTML::WindowProxy>> open(StringView url, StringView name, StringView features);
@ -828,7 +828,7 @@ public:
Vector<GC::Root<Range>> find_matching_text(String const&, CaseSensitivity); Vector<GC::Root<Range>> find_matching_text(String const&, CaseSensitivity);
void parse_html_from_a_string(StringView); void parse_html_from_a_string(StringView);
static GC::Ref<Document> parse_html_unsafe(JS::VM&, StringView); static WebIDL::ExceptionOr<GC::Root<DOM::Document>> parse_html_unsafe(JS::VM&, TrustedTypes::TrustedHTMLOrString const&);
void set_console_client(GC::Ptr<JS::ConsoleClient> console_client) { m_console_client = console_client; } void set_console_client(GC::Ptr<JS::ConsoleClient> console_client) { m_console_client = console_client; }
GC::Ptr<JS::ConsoleClient> console_client() const { return m_console_client; } GC::Ptr<JS::ConsoleClient> console_client() const { return m_console_client; }
@ -972,7 +972,7 @@ private:
Yes, Yes,
No, No,
}; };
WebIDL::ExceptionOr<void> run_the_document_write_steps(Vector<String> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink); WebIDL::ExceptionOr<void> run_the_document_write_steps(Vector<TrustedTypes::TrustedHTMLOrString> const& text, AddLineFeed line_feed, TrustedTypes::InjectionSink sink);
void queue_intersection_observer_task(); void queue_intersection_observer_task();
void queue_an_intersection_observer_entry(IntersectionObserver::IntersectionObserver&, HighResolutionTime::DOMHighResTimeStamp time, GC::Ref<Geometry::DOMRectReadOnly> root_bounds, GC::Ref<Geometry::DOMRectReadOnly> bounding_client_rect, GC::Ref<Geometry::DOMRectReadOnly> intersection_rect, bool is_intersecting, double intersection_ratio, GC::Ref<Element> target); void queue_an_intersection_observer_entry(IntersectionObserver::IntersectionObserver&, HighResolutionTime::DOMHighResTimeStamp time, GC::Ref<Geometry::DOMRectReadOnly> root_bounds, GC::Ref<Geometry::DOMRectReadOnly> bounding_client_rect, GC::Ref<Geometry::DOMRectReadOnly> intersection_rect, bool is_intersecting, double intersection_ratio, GC::Ref<Element> target);

View File

@ -26,6 +26,7 @@
#import <HTML/HTMLScriptElement.idl> #import <HTML/HTMLScriptElement.idl>
#import <HTML/Location.idl> #import <HTML/Location.idl>
#import <Selection/Selection.idl> #import <Selection/Selection.idl>
#import <TrustedTypes/TrustedHTML.idl>
#import <ViewTransition/ViewTransition.idl> #import <ViewTransition/ViewTransition.idl>
#import <XPath/XPathResult.idl> #import <XPath/XPathResult.idl>
#import <XPath/XPathExpression.idl> #import <XPath/XPathExpression.idl>
@ -56,13 +57,10 @@ interface Document : Node {
[CEReactions] Document open(optional DOMString unused1, optional DOMString unused2); [CEReactions] Document open(optional DOMString unused1, optional DOMString unused2);
WindowProxy? open(USVString url, DOMString name, DOMString features); WindowProxy? open(USVString url, DOMString name, DOMString features);
[CEReactions] undefined close(); [CEReactions] undefined close();
// FIXME: [CEReactions] undefined write((TrustedHTML or DOMString)... text); [CEReactions] undefined write((TrustedHTML or Utf16DOMString)... text);
[CEReactions] undefined write(DOMString... text); [CEReactions] undefined writeln((TrustedHTML or Utf16DOMString)... text);
// FIXME: [CEReactions] undefined writeln((TrustedHTML or DOMString)... text);
[CEReactions] undefined writeln(DOMString... text);
// FIXME: static Document parseHTMLUnsafe((TrustedHTML or DOMString) html); static Document parseHTMLUnsafe((TrustedHTML or Utf16DOMString) html);
static Document parseHTMLUnsafe(DOMString html);
attribute DOMString cookie; attribute DOMString cookie;

View File

@ -17,6 +17,7 @@ namespace Web::TrustedTypes {
// https://w3c.github.io/trusted-types/dist/spec/#injection-sink // https://w3c.github.io/trusted-types/dist/spec/#injection-sink
#define ENUMERATE_INJECTION_SINKS \ #define ENUMERATE_INJECTION_SINKS \
__ENUMERATE_INJECTION_SINKS(DocumentparseHTMLUnsafe, "Document parseHTMLUnsafe") \
__ENUMERATE_INJECTION_SINKS(Documentwrite, "Document write") \ __ENUMERATE_INJECTION_SINKS(Documentwrite, "Document write") \
__ENUMERATE_INJECTION_SINKS(Documentwriteln, "Document writeln") \ __ENUMERATE_INJECTION_SINKS(Documentwriteln, "Document writeln") \
__ENUMERATE_INJECTION_SINKS(DocumentexecCommand, "Document execCommand") \ __ENUMERATE_INJECTION_SINKS(DocumentexecCommand, "Document execCommand") \