LibWeb/CSP: Implement SecurityPolicyViolationEvent

This is used to report violations of policies to the element/global
object that caused it.
This commit is contained in:
Luke Wilde 2024-11-26 15:43:02 +00:00 committed by Alexander Kalenik
parent 564cd1849b
commit 02236be737
Notes: github-actions[bot] 2025-03-18 23:56:31 +00:00
9 changed files with 168 additions and 0 deletions

View file

@ -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

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/SecurityPolicyViolationEventPrototype.h>
#include <LibWeb/ContentSecurityPolicy/SecurityPolicyViolationEvent.h>
namespace Web::ContentSecurityPolicy {
GC_DEFINE_ALLOCATOR(SecurityPolicyViolationEvent);
GC::Ref<SecurityPolicyViolationEvent> SecurityPolicyViolationEvent::create(JS::Realm& realm, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init)
{
return realm.create<SecurityPolicyViolationEvent>(realm, event_name, event_init);
}
WebIDL::ExceptionOr<GC::Ref<SecurityPolicyViolationEvent>> SecurityPolicyViolationEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, SecurityPolicyViolationEventInit const& event_init)
{
return realm.create<SecurityPolicyViolationEvent>(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);
}
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2025, Luke Wilde <luke@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/Bindings/SecurityPolicyViolationEventPrototype.h>
#include <LibWeb/DOM/Event.h>
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<SecurityPolicyViolationEvent> create(JS::Realm&, FlyString const& event_name, SecurityPolicyViolationEventInit const& = {});
static WebIDL::ExceptionOr<GC::Ref<SecurityPolicyViolationEvent>> 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 };
};
}

View file

@ -0,0 +1,40 @@
#import <DOM/Event.idl>
// 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;
};

View file

@ -102,6 +102,8 @@ class DecompressionStream;
namespace Web::ContentSecurityPolicy {
class Policy;
class PolicyList;
class SecurityPolicyViolationEvent;
struct SecurityPolicyViolationEventInit;
struct SerializedPolicy;
}

View file

@ -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)

View file

@ -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;

View file

@ -16,6 +16,7 @@ static constexpr Array libweb_interface_namespaces = {
"CSS"sv,
"Clipboard"sv,
"Compression"sv,
"ContentSecurityPolicy"sv,
"Crypto"sv,
"DOM"sv,
"DOMURL"sv,

View file

@ -358,6 +358,7 @@ SVGTransformList
SVGUseElement
Screen
ScreenOrientation
SecurityPolicyViolationEvent
Selection
ServiceWorker
ServiceWorkerContainer