diff --git a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.cpp b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.cpp index e68bec7a41e..38bad0f4ca1 100644 --- a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.cpp +++ b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.cpp @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include namespace Web::TrustedTypes { @@ -28,4 +31,98 @@ void TrustedTypePolicy::initialize(JS::Realm& realm) Base::initialize(realm); } +// https://w3c.github.io/trusted-types/dist/spec/#dom-trustedtypepolicy-createhtml +WebIDL::ExceptionOr> TrustedTypePolicy::create_html(String const& input, GC::RootVector const& arguments) +{ + // 1. Returns the result of executing the Create a Trusted Type algorithm, with the following arguments: + // policy + // this value + // trustedTypeName + // "TrustedHTML" + // value + // input + // arguments + // arguments + return create_a_trusted_type(TrustedTypeName::TrustedHTML, input, arguments); +} + +// https://w3c.github.io/trusted-types/dist/spec/#create-a-trusted-type-algorithm +WebIDL::ExceptionOr> TrustedTypePolicy::create_a_trusted_type(TrustedTypeName trusted_type_name, String const& value, GC::RootVector const& arguments) +{ + auto& vm = this->vm(); + auto& realm = this->realm(); + + // 1. Let policyValue be the result of executing Get Trusted Type policy value with the same arguments + // as this algorithm and additionally true as throwIfMissing. + // 2. If the algorithm threw an error, rethrow the error and abort the following steps. + auto const policy_value = TRY(get_trusted_type_policy_value(trusted_type_name, value, arguments, ThrowIfCallbackMissing::Yes)); + + // 3. Let dataString be the result of stringifying policyValue. + Utf16String data_string; + switch (trusted_type_name) { + case TrustedTypeName::TrustedHTML: + case TrustedTypeName::TrustedScript: + data_string = TRY(WebIDL::to_utf16_string(vm, policy_value)); + break; + case TrustedTypeName::TrustedScriptURL: + data_string = TRY(WebIDL::to_utf16_usv_string(vm, policy_value)); + break; + default: + VERIFY_NOT_REACHED(); + } + + // 4. If policyValue is null or undefined, set dataString to the empty string. + if (policy_value.is_nullish()) + data_string = ""_utf16; + + // 5. Return a new instance of an interface with a type name trustedTypeName, with its associated data value set to dataString. + return realm.create(realm, move(data_string)); +} + +// https://w3c.github.io/trusted-types/dist/spec/#abstract-opdef-get-trusted-type-policy-value +WebIDL::ExceptionOr TrustedTypePolicy::get_trusted_type_policy_value(TrustedTypeName trusted_type_name, String const& value, GC::RootVector const& values, ThrowIfCallbackMissing throw_if_missing) +{ + auto& vm = this->vm(); + + // 1. Let functionName be a function name for the given trustedTypeName, based on the following table: + // 2. Let function be policy’s options[functionName]. + GC::Ptr function; + switch (trusted_type_name) { + case TrustedTypeName::TrustedHTML: + function = m_options.create_html; + break; + case TrustedTypeName::TrustedScript: + function = m_options.create_script; + break; + case TrustedTypeName::TrustedScriptURL: + function = m_options.create_script_url; + break; + default: + VERIFY_NOT_REACHED(); + } + + // 3. If function is null, then: + if (!function) { + // 1. If throwIfMissing throw a TypeError. + if (throw_if_missing == ThrowIfCallbackMissing::Yes) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Trying to create a trusted type without a callback"_string }; + + // 2. Else return null + return JS::js_null(); + } + + // 4. Let args be << value >>. + GC::RootVector args(heap()); + args.append(JS::PrimitiveString::create(vm, value)); + + // 5. Append each item in arguments to args. + args.extend(values); + + // 6. Let policyValue be the result of invoking function with args and "rethrow". + auto const policy_value = TRY(WebIDL::invoke_callback(*function, {}, WebIDL::ExceptionBehavior::Rethrow, args)); + + // 7. Return policyValue. + return policy_value; +} + } diff --git a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.h b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.h index 78a0a18ffee..95aa5bc3171 100644 --- a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.h +++ b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.h @@ -12,6 +12,17 @@ namespace Web::TrustedTypes { +enum class TrustedTypeName { + TrustedHTML, + TrustedScript, + TrustedScriptURL, +}; + +enum class ThrowIfCallbackMissing { + Yes, + No +}; + struct TrustedTypePolicyOptions { GC::Root create_html; GC::Root create_script; @@ -27,10 +38,16 @@ public: String const& name() const { return m_name; } + WebIDL::ExceptionOr> create_html(String const&, GC::RootVector const&); + private: explicit TrustedTypePolicy(JS::Realm&, String const&, TrustedTypePolicyOptions const&); virtual void initialize(JS::Realm&) override; + WebIDL::ExceptionOr> create_a_trusted_type(TrustedTypeName, String const&, GC::RootVector const& values); + + WebIDL::ExceptionOr get_trusted_type_policy_value(TrustedTypeName, String const& value, GC::RootVector const& values, ThrowIfCallbackMissing throw_if_missing); + String const m_name; TrustedTypePolicyOptions const m_options; }; diff --git a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.idl b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.idl index ed839564a46..7a7b36c921f 100644 --- a/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.idl +++ b/Libraries/LibWeb/TrustedTypes/TrustedTypePolicy.idl @@ -1,8 +1,10 @@ +#import + // https://w3c.github.io/trusted-types/dist/spec/#trusted-type-policy [Exposed=(Window,Worker)] interface TrustedTypePolicy { readonly attribute DOMString name; - [FIXME] TrustedHTML createHTML(DOMString input, any... arguments); + TrustedHTML createHTML(DOMString input, any... arguments); [FIXME] TrustedScript createScript(DOMString input, any... arguments); [FIXME] TrustedScriptURL createScriptURL(DOMString input, any... arguments); };