LibURL: Add ability to store whether an origin is a file scheme origin

This commit is contained in:
Shannon Booth 2025-12-31 15:04:17 +01:00 committed by Jelle Raaijmakers
parent 5bbd3c9d31
commit 64532bcfa0
5 changed files with 30 additions and 19 deletions

View file

@ -136,8 +136,9 @@ ErrorOr<URL::Origin> decode(Decoder& decoder)
{
auto is_opaque = TRY(decoder.decode<bool>());
if (is_opaque) {
auto nonce = TRY(decoder.decode<URL::Origin::Nonce>());
return URL::Origin { nonce };
auto nonce = TRY(decoder.decode<URL::Origin::OpaqueData::Nonce>());
auto type = TRY(decoder.decode<URL::Origin::OpaqueData::Type>());
return URL::Origin { URL::Origin::OpaqueData { nonce, type } };
}
auto scheme = TRY(decoder.decode<Optional<String>>());

View file

@ -149,7 +149,8 @@ ErrorOr<void> encode(Encoder& encoder, URL::Origin const& origin)
{
if (origin.is_opaque()) {
TRY(encoder.encode(true));
TRY(encoder.encode(origin.nonce()));
TRY(encoder.encode(origin.opaque_data().nonce));
TRY(encoder.encode(origin.opaque_data().type));
} else {
TRY(encoder.encode(false));
TRY(encoder.encode(origin.scheme()));

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024-2025, Shannon Booth <shannon@serenityos.org>
* Copyright (c) 2024-2026, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -11,9 +11,9 @@
namespace URL {
Origin Origin::create_opaque()
Origin Origin::create_opaque(OpaqueData::Type type)
{
return Origin { AK::get_random<Nonce>() };
return Origin { OpaqueData { get_random<OpaqueData::Nonce>(), type } };
}
// https://html.spec.whatwg.org/multipage/browsers.html#same-site
@ -67,8 +67,8 @@ namespace AK {
unsigned Traits<URL::Origin>::hash(URL::Origin const& origin)
{
if (origin.is_opaque()) {
auto const& nonce = origin.nonce();
// Random data, so the first u32 is as good as hashing the entire thing.
auto const& nonce = origin.opaque_data().nonce;
// Random data, so the first u32 of the nonce is as good as hashing the entire thing.
return (static_cast<u32>(nonce[0]) << 24)
| (static_cast<u32>(nonce[1]) << 16)
| (static_cast<u32>(nonce[2]) << 8)

View file

@ -17,14 +17,23 @@ namespace URL {
// https://html.spec.whatwg.org/multipage/browsers.html#concept-origin
class Origin {
public:
using Nonce = Array<u8, 16>;
struct OpaqueData {
enum class Type : u8 {
Standard,
File
};
using Nonce = Array<u8, 16>;
explicit Origin(Nonce nonce)
: m_state(move(nonce))
Nonce nonce;
Type type;
};
explicit Origin(OpaqueData opaque_data)
: m_state(opaque_data)
{
}
static Origin create_opaque();
static Origin create_opaque(OpaqueData::Type = OpaqueData::Type::Standard);
Origin(Optional<String> const& scheme, Host const& host, Optional<u16> port, Optional<String> domain = {})
: m_state(Tuple {
@ -37,21 +46,21 @@ public:
}
// https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque
bool is_opaque() const { return m_state.has<Nonce>(); }
bool is_opaque() const { return m_state.has<OpaqueData>(); }
Optional<String> const& scheme() const { return m_state.get<Tuple>().scheme; }
Host const& host() const { return m_state.get<Tuple>().host; }
Optional<u16> port() const { return m_state.get<Tuple>().port; }
Optional<String> domain() const { return m_state.get<Tuple>().domain; }
Nonce const& nonce() const { return m_state.get<Nonce>(); }
OpaqueData const& opaque_data() const { return m_state.get<OpaqueData>(); }
// https://html.spec.whatwg.org/multipage/origin.html#same-origin
bool is_same_origin(Origin const& other) const
{
// 1. If A and B are the same opaque origin, then return true.
if (is_opaque() && other.is_opaque())
return nonce() == other.nonce();
return opaque_data().nonce == other.opaque_data().nonce;
// 2. If A and B are both tuple origins and their schemes, hosts, and port are identical, then return true.
if (!is_opaque() && !other.is_opaque()
@ -70,7 +79,7 @@ public:
{
// 1. If A and B are the same opaque origin, then return true.
if (is_opaque() && other.is_opaque())
return nonce() == other.nonce();
return opaque_data().nonce == other.opaque_data().nonce;
// 2. If A and B are both tuple origins, run these substeps:
if (!is_opaque() && !other.is_opaque()) {
@ -110,7 +119,7 @@ public:
return Host { tuple.domain.value() };
// 3. Return origin's host.
return m_state.get<Tuple>().host;
return tuple.host;
}
bool operator==(Origin const& other) const { return is_same_origin(other); }
@ -123,7 +132,7 @@ private:
Optional<String> domain;
};
Variant<Tuple, Nonce> m_state;
Variant<Tuple, OpaqueData> m_state;
};
}

View file

@ -37,7 +37,7 @@ bool Site::is_same_site(Site const& other) const
// 1. If A and B are the same opaque origin, then return true.
// NOTE: Origins in sites are always opaque.
if (m_value.has<Origin>() && other.m_value.has<Origin>())
return m_value.get<Origin>().nonce() == other.m_value.get<Origin>().nonce();
return m_value.get<Origin>().opaque_data().nonce == other.m_value.get<Origin>().opaque_data().nonce;
// 2. If A or B is an opaque origin, then return false.
if (m_value.has<Origin>() || other.m_value.has<Origin>())