mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-26 01:35:08 +02:00
LibWeb/Bindings: Implement [SecureContext] extended attribute
Unfortunately this is a bit of a pain to test as it is surprisingly difficult to create a non secure context in our test harness. This is because both file scheme URLs and localhost are considered secure contexts. To test this, add a very specific internals setter to change the top level origin of the environment for the current realm.
This commit is contained in:
committed by
Shannon Booth
parent
6bdced0014
commit
bc93ba4530
Notes:
github-actions[bot]
2026-02-14 19:35:46 +00:00
Author: https://github.com/shannonbooth Commit: https://github.com/LadybirdBrowser/ladybird/commit/bc93ba45306 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/7518
@@ -120,6 +120,7 @@ static ErrorOr<void> generate_intrinsic_definitions_implementation(StringView ou
|
||||
#include <LibGC/DeferGC.h>
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/PrincipalHostDefined.h>
|
||||
#include <LibWeb/Export.h>
|
||||
#include <LibWeb/HTML/Window.h>
|
||||
#include <LibWeb/HTML/DedicatedWorkerGlobalScope.h>
|
||||
@@ -182,6 +183,27 @@ void Intrinsics::create_web_namespace<@namespace_class@>(JS::Realm& realm)
|
||||
)~~~");
|
||||
};
|
||||
|
||||
generator.append(R"~~~(
|
||||
static bool is_secure_context_interface(InterfaceName name)
|
||||
{
|
||||
switch (name) {
|
||||
)~~~");
|
||||
for (auto const& interface : interface_sets.intrinsics) {
|
||||
if (!interface.extended_attributes.contains("SecureContext"))
|
||||
continue;
|
||||
|
||||
generator.set("secure_context_interface_name", interface.name);
|
||||
generator.append(R"~~~(
|
||||
case InterfaceName::@secure_context_interface_name@:)~~~");
|
||||
}
|
||||
generator.append(R"~~~(
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
)~~~");
|
||||
|
||||
auto generate_global_exposed = [&generator](StringView global_name, Vector<IDL::Interface&> const& interface_set) {
|
||||
generator.set("global_name", global_name);
|
||||
generator.append(R"~~~(
|
||||
@@ -235,8 +257,11 @@ bool is_exposed(InterfaceName name, JS::Realm& realm)
|
||||
TODO(); // FIXME: ServiceWorkerGlobalScope and WorkletGlobalScope.
|
||||
}
|
||||
|
||||
// FIXME: 2. If realm’s settings object is not a secure context, and construct is conditionally exposed on
|
||||
// [SecureContext], then return false.
|
||||
// 2. If realm’s settings object is not a secure context, and construct is conditionally exposed on
|
||||
// [SecureContext], then return false.
|
||||
if (is_secure_context_interface(name) && HTML::is_non_secure_context(principal_host_defined_environment_settings_object(realm)))
|
||||
return false;
|
||||
|
||||
// FIXME: 3. If realm’s settings object’s cross-origin isolated capability is false, and construct is
|
||||
// conditionally exposed on [CrossOriginIsolated], then return false.
|
||||
|
||||
@@ -352,6 +377,7 @@ static ErrorOr<void> generate_exposed_interface_implementation(StringView class_
|
||||
#include <LibJS/Runtime/Object.h>
|
||||
#include <LibWeb/Bindings/Intrinsics.h>
|
||||
#include <LibWeb/Bindings/@global_object_name@ExposedInterfaces.h>
|
||||
#include <LibWeb/HTML/Scripting/Environments.h>
|
||||
)~~~");
|
||||
for (auto& interface : exposed_interfaces) {
|
||||
auto gen = generator.fork();
|
||||
@@ -382,6 +408,7 @@ namespace Web::Bindings {
|
||||
void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global)
|
||||
{
|
||||
static constexpr u8 attr = JS::Attribute::Writable | JS::Attribute::Configurable;
|
||||
[[maybe_unused]] bool is_secure_context = HTML::is_secure_context(HTML::relevant_principal_settings_object(global));
|
||||
)~~~");
|
||||
|
||||
auto add_interface = [class_name](SourceGenerator& gen, IDL::Interface const& interface) {
|
||||
@@ -393,6 +420,11 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global)
|
||||
gen.set("interface_name", interface.namespaced_name);
|
||||
gen.set("prototype_class", interface.prototype_class);
|
||||
|
||||
if (interface.extended_attributes.contains("SecureContext")) {
|
||||
gen.append(R"~~~(
|
||||
if (is_secure_context) {)~~~");
|
||||
}
|
||||
|
||||
gen.append(R"~~~(
|
||||
global.define_intrinsic_accessor("@interface_name@"_utf16_fly_string, attr, [](auto& realm) -> JS::Value { return &ensure_web_constructor<@prototype_class@>(realm, "@interface_name@"_fly_string); });)~~~");
|
||||
|
||||
@@ -417,6 +449,11 @@ void add_@global_object_snake_name@_exposed_interfaces(JS::Object& global)
|
||||
gen.append(R"~~~(
|
||||
global.define_intrinsic_accessor("@legacy_interface_name@"_utf16_fly_string, attr, [](auto& realm) -> JS::Value { return &ensure_web_constructor<@prototype_class@>(realm, "@legacy_interface_name@"_fly_string); });)~~~");
|
||||
}
|
||||
|
||||
if (interface.extended_attributes.contains("SecureContext")) {
|
||||
gen.append(R"~~~(
|
||||
})~~~");
|
||||
}
|
||||
};
|
||||
|
||||
auto add_namespace = [](SourceGenerator& gen, StringView name, StringView namespace_class) {
|
||||
|
||||
Reference in New Issue
Block a user