diff --git a/Libraries/LibWeb/CMakeLists.txt b/Libraries/LibWeb/CMakeLists.txt index ab4e1a6cc79..33264d511a7 100644 --- a/Libraries/LibWeb/CMakeLists.txt +++ b/Libraries/LibWeb/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCES ContentSecurityPolicy/Directives/SerializedDirective.cpp ContentSecurityPolicy/Policy.cpp ContentSecurityPolicy/PolicyList.cpp + ContentSecurityPolicy/SecurityPolicyViolationEvent.cpp ContentSecurityPolicy/SerializedPolicy.cpp CredentialManagement/Credential.cpp CredentialManagement/CredentialsContainer.cpp diff --git a/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.cpp b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.cpp new file mode 100644 index 00000000000..805b71c17bc --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +namespace Web::ContentSecurityPolicy { + +GC_DEFINE_ALLOCATOR(SecurityPolicyViolationEvent); + +GC::Ref SecurityPolicyViolationEvent::create(JS::Realm& realm, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init) +{ + return realm.create(realm, event_name, event_init); +} + +WebIDL::ExceptionOr> SecurityPolicyViolationEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init) +{ + return realm.create(realm, event_name, event_init); +} + +SecurityPolicyViolationEvent::SecurityPolicyViolationEvent(JS::Realm& realm, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init) + : Event(realm, event_name, event_init) + , m_document_uri(event_init.document_uri) + , m_referrer(event_init.referrer) + , m_blocked_uri(event_init.blocked_uri) + , m_violated_directive(event_init.violated_directive) + , m_effective_directive(event_init.effective_directive) + , m_original_policy(event_init.original_policy) + , m_source_file(event_init.source_file) + , m_sample(event_init.sample) + , m_disposition(event_init.disposition) + , m_status_code(event_init.status_code) + , m_line_number(event_init.line_number) + , m_column_number(event_init.column_number) +{ +} + +SecurityPolicyViolationEvent::~SecurityPolicyViolationEvent() = default; + +void SecurityPolicyViolationEvent::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + WEB_SET_PROTOTYPE_FOR_INTERFACE(SecurityPolicyViolationEvent); +} + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.h b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.h new file mode 100644 index 00000000000..1c2867a3495 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, Luke Wilde + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::ContentSecurityPolicy { + +struct SecurityPolicyViolationEventInit final : public DOM::EventInit { + String document_uri; + String referrer; + String blocked_uri; + String violated_directive; + String effective_directive; + String original_policy; + String source_file; + String sample; + Bindings::SecurityPolicyViolationEventDisposition disposition { Bindings::SecurityPolicyViolationEventDisposition::Enforce }; + u16 status_code { 0 }; + u32 line_number { 0 }; + u32 column_number { 0 }; +}; + +class SecurityPolicyViolationEvent final : public DOM::Event { + WEB_PLATFORM_OBJECT(SecurityPolicyViolationEvent, DOM::Event); + GC_DECLARE_ALLOCATOR(SecurityPolicyViolationEvent); + +public: + [[nodiscard]] static GC::Ref create(JS::Realm&, FlyString const& event_name, SecurityPolicyViolationEventInit const& = {}); + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init); + + virtual ~SecurityPolicyViolationEvent() override; + + String const& document_uri() const { return m_document_uri; } + String const& referrer() const { return m_referrer; } + String const& blocked_uri() const { return m_blocked_uri; } + String const& violated_directive() const { return m_violated_directive; } + String const& effective_directive() const { return m_effective_directive; } + String const& original_policy() const { return m_original_policy; } + String const& source_file() const { return m_source_file; } + String const& sample() const { return m_sample; } + Bindings::SecurityPolicyViolationEventDisposition disposition() const { return m_disposition; } + u16 status_code() const { return m_status_code; } + u32 line_number() const { return m_line_number; } + u32 column_number() const { return m_column_number; } + +private: + SecurityPolicyViolationEvent(JS::Realm&, FlyString const& event_name, SecurityPolicyViolationEventInit const&); + + virtual void initialize(JS::Realm&) override; + + String m_document_uri; + String m_referrer; + String m_blocked_uri; + String m_violated_directive; + String m_effective_directive; + String m_original_policy; + String m_source_file; + String m_sample; + Bindings::SecurityPolicyViolationEventDisposition m_disposition { Bindings::SecurityPolicyViolationEventDisposition::Enforce }; + u16 m_status_code { 0 }; + u32 m_line_number { 0 }; + u32 m_column_number { 0 }; +}; + +} diff --git a/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.idl b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.idl new file mode 100644 index 00000000000..c73dc935993 --- /dev/null +++ b/Libraries/LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.idl @@ -0,0 +1,40 @@ +#import + +// https://w3c.github.io/webappsec-csp/#enumdef-securitypolicyviolationeventdisposition +enum SecurityPolicyViolationEventDisposition { + "enforce", + "report" +}; + +// https://w3c.github.io/webappsec-csp/#securitypolicyviolationevent +[Exposed=(Window,Worker)] +interface SecurityPolicyViolationEvent : Event { + constructor(DOMString type, optional SecurityPolicyViolationEventInit eventInitDict = {}); + readonly attribute USVString documentURI; + readonly attribute USVString referrer; + readonly attribute USVString blockedURI; + readonly attribute DOMString effectiveDirective; + readonly attribute DOMString violatedDirective; // historical alias of effectiveDirective + readonly attribute DOMString originalPolicy; + readonly attribute USVString sourceFile; + readonly attribute DOMString sample; + readonly attribute SecurityPolicyViolationEventDisposition disposition; + readonly attribute unsigned short statusCode; + readonly attribute unsigned long lineNumber; + readonly attribute unsigned long columnNumber; +}; + +dictionary SecurityPolicyViolationEventInit : EventInit { + USVString documentURI = ""; + USVString referrer = ""; + USVString blockedURI = ""; + DOMString violatedDirective = ""; + DOMString effectiveDirective = ""; + DOMString originalPolicy = ""; + USVString sourceFile = ""; + DOMString sample = ""; + SecurityPolicyViolationEventDisposition disposition = "enforce"; + unsigned short statusCode = 0; + unsigned long lineNumber = 0; + unsigned long columnNumber = 0; +}; diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index 8389057b448..f93dc380a7d 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -102,6 +102,8 @@ class DecompressionStream; namespace Web::ContentSecurityPolicy { class Policy; class PolicyList; +class SecurityPolicyViolationEvent; +struct SecurityPolicyViolationEventInit; struct SerializedPolicy; } diff --git a/Libraries/LibWeb/idl_files.cmake b/Libraries/LibWeb/idl_files.cmake index 487a78ef9d4..d12820fbe1e 100644 --- a/Libraries/LibWeb/idl_files.cmake +++ b/Libraries/LibWeb/idl_files.cmake @@ -10,6 +10,7 @@ libweb_js_bindings(Animations/KeyframeEffect) libweb_js_bindings(Clipboard/Clipboard) libweb_js_bindings(Clipboard/ClipboardEvent) libweb_js_bindings(Clipboard/ClipboardItem) +libweb_js_bindings(ContentSecurityPolicy/SecurityPolicyViolationEvent) libweb_js_bindings(Compression/CompressionStream) libweb_js_bindings(Compression/DecompressionStream) libweb_js_bindings(CredentialManagement/Credential) diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 4fdc25356d7..5763a99856a 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -4501,6 +4501,7 @@ static void generate_using_namespace_definitions(SourceGenerator& generator) // FIXME: This is a total hack until we can figure out the namespace for a given type somehow. using namespace Web::Animations; using namespace Web::Clipboard; +using namespace Web::ContentSecurityPolicy; using namespace Web::CredentialManagement; using namespace Web::Crypto; using namespace Web::CSS; diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h index fce40c45351..c9dbf2167c5 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/Namespaces.h @@ -16,6 +16,7 @@ static constexpr Array libweb_interface_namespaces = { "CSS"sv, "Clipboard"sv, "Compression"sv, + "ContentSecurityPolicy"sv, "Crypto"sv, "DOM"sv, "DOMURL"sv, diff --git a/Tests/LibWeb/Text/expected/all-window-properties.txt b/Tests/LibWeb/Text/expected/all-window-properties.txt index d15c07921ff..787ba16db73 100644 --- a/Tests/LibWeb/Text/expected/all-window-properties.txt +++ b/Tests/LibWeb/Text/expected/all-window-properties.txt @@ -358,6 +358,7 @@ SVGTransformList SVGUseElement Screen ScreenOrientation +SecurityPolicyViolationEvent Selection ServiceWorker ServiceWorkerContainer