Files
ladybird/Libraries/LibWeb/PermissionsPolicy/AutoplayAllowlist.cpp
Shannon Booth e188de89f9 LibWeb/PermissionsPolicy: Allow autoplay of file:// media from file://
As file:// URLs are considered opaque origins by default, we need
to special case them in the allowlist as any opaque origin will
not be matched in the allow list.
2026-03-01 01:04:10 +01:00

99 lines
3.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2023-2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/String.h>
#include <LibURL/Origin.h>
#include <LibURL/Parser.h>
#include <LibURL/URL.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOMURL/DOMURL.h>
#include <LibWeb/PermissionsPolicy/AutoplayAllowlist.h>
// FIXME: This is an ad-hoc implementation of the "autoplay" policy-controlled feature:
// https://w3c.github.io/webappsec-permissions-policy/#policy-controlled-feature
namespace Web::PermissionsPolicy {
AutoplayAllowlist& AutoplayAllowlist::the()
{
static AutoplayAllowlist filter;
return filter;
}
AutoplayAllowlist::AutoplayAllowlist() = default;
AutoplayAllowlist::~AutoplayAllowlist() = default;
// https://w3c.github.io/webappsec-permissions-policy/#is-feature-enabled
Decision AutoplayAllowlist::is_allowed_for_origin(DOM::Document const& document, URL::Origin const& origin) const
{
// FIXME: 1. Let policy be documents Permissions Policy
// FIXME: 2. If policys inherited policy for feature is Disabled, return "Disabled".
// 3. If feature is present in policys declared policy:
if (m_allowlist.has_value()) {
// 1. If the allowlist for feature in policys declared policy matches origin, then return "Enabled".
// 2. Otherwise return "Disabled".
return m_allowlist->visit(
[](Global) {
return Decision::Enabled;
},
[&](auto const& patterns) {
for (auto const& pattern : patterns) {
if (pattern.is_same_origin_domain(origin))
return Decision::Enabled;
// AD-HOC: Allow autoplay for file:// URLs if the document is also from a file:// URL.
if (origin.is_opaque_file_origin() && document.origin().is_opaque_file_origin())
return Decision::Enabled;
}
return Decision::Disabled;
});
}
// 4. If features default allowlist is *, return "Enabled".
// 5. If features default allowlist is 'self', and origin is same origin with documents origin, return "Enabled".
// NOTE: The "autoplay" feature's default allowlist is 'self'.
// https://html.spec.whatwg.org/multipage/infrastructure.html#autoplay-feature
if (origin.is_same_origin(document.origin()))
return Decision::Enabled;
// AD-HOC: Allow autoplay for file:// URLs if the document is also from a file:// URL.
if (origin.is_opaque_file_origin() && document.origin().is_opaque_file_origin())
return Decision::Enabled;
// 6. Return "Disabled".
return Decision::Disabled;
}
void AutoplayAllowlist::enable_globally()
{
m_allowlist = Global {};
}
void AutoplayAllowlist::enable_for_origins(ReadonlySpan<String> origins)
{
m_allowlist = Patterns {};
auto& allowlist = m_allowlist->get<Patterns>();
allowlist.ensure_capacity(origins.size());
for (auto const& origin : origins) {
auto url = URL::Parser::basic_parse(origin);
if (!url.has_value())
url = URL::Parser::basic_parse(MUST(String::formatted("https://{}", origin)));
if (!url.has_value()) {
dbgln("Invalid origin for autoplay allowlist: {}", origin);
continue;
}
allowlist.append(url->origin());
}
}
}