ladybird/Userland/Libraries/LibWeb/HTML/Origin.h
Shannon Booth e800605ad3 AK+LibURL: Move AK::URL into a new URL library
This URL library ends up being a relatively fundamental base library of
the system, as LibCore depends on LibURL.

This change has two main benefits:
 * Moving AK back more towards being an agnostic library that can
   be used between the kernel and userspace. URL has never really fit
   that description - and is not used in the kernel.
 * URL _should_ depend on LibUnicode, as it needs punnycode support.
   However, it's not really possible to do this inside of AK as it can't
   depend on any external library. This change brings us a little closer
   to being able to do that, but unfortunately we aren't there quite
   yet, as the code generators depend on LibCore.
2024-03-18 14:06:28 -04:00

145 lines
4.5 KiB
C++

/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/ByteString.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
#include <LibURL/Parser.h>
#include <LibURL/URL.h>
namespace Web::HTML {
class Origin {
public:
Origin() = default;
Origin(Optional<ByteString> const& scheme, URL::Host const& host, u16 port)
: m_scheme(scheme)
, m_host(host)
, m_port(port)
{
}
// https://html.spec.whatwg.org/multipage/origin.html#concept-origin-opaque
bool is_opaque() const { return !m_scheme.has_value() && m_host.has<Empty>() && m_port == 0; }
StringView scheme() const
{
return m_scheme.map([](auto& str) { return str.view(); }).value_or(StringView {});
}
URL::Host const& host() const { return m_host; }
u16 port() const { return m_port; }
// 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 true;
// 2. If A and B are both tuple origins and their schemes, hosts, and port are identical, then return true.
// 3. Return false.
return scheme() == other.scheme()
&& host() == other.host()
&& port() == other.port();
}
// https://html.spec.whatwg.org/multipage/origin.html#same-origin-domain
bool is_same_origin_domain(Origin const& other) const
{
// 1. If A and B are the same opaque origin, then return true.
if (is_opaque() && other.is_opaque())
return true;
// 2. If A and B are both tuple origins, run these substeps:
if (!is_opaque() && !other.is_opaque()) {
// 1. If A and B's schemes are identical, and their domains are identical and non-null, then return true.
// FIXME: Check domains once supported.
if (scheme() == other.scheme())
return true;
// 2. Otherwise, if A and B are same origin and their domains are identical and null, then return true.
// FIXME: Check domains once supported.
if (is_same_origin(other))
return true;
}
// 3. Return false.
return false;
}
// https://html.spec.whatwg.org/multipage/origin.html#ascii-serialisation-of-an-origin
ByteString serialize() const
{
// 1. If origin is an opaque origin, then return "null"
if (is_opaque())
return "null";
// 2. Otherwise, let result be origin's scheme.
StringBuilder result;
result.append(scheme());
// 3. Append "://" to result.
result.append("://"sv);
// 4. Append origin's host, serialized, to result.
result.append(URL::Parser::serialize_host(host()).release_value_but_fixme_should_propagate_errors().to_byte_string());
// 5. If origin's port is non-null, append a U+003A COLON character (:), and origin's port, serialized, to result.
if (port() != 0) {
result.append(':');
result.append(ByteString::number(port()));
}
// 6. Return result
return result.to_byte_string();
}
// https://html.spec.whatwg.org/multipage/origin.html#concept-origin-effective-domain
Optional<URL::Host> effective_domain() const
{
// 1. If origin is an opaque origin, then return null.
if (is_opaque())
return {};
// FIXME: 2. If origin's domain is non-null, then return origin's domain.
// 3. Return origin's host.
return m_host;
}
bool operator==(Origin const& other) const { return is_same_origin(other); }
private:
Optional<ByteString> m_scheme;
URL::Host m_host;
u16 m_port { 0 };
};
}
namespace AK {
template<>
struct Traits<Web::HTML::Origin> : public DefaultTraits<Web::HTML::Origin> {
static unsigned hash(Web::HTML::Origin const& origin)
{
auto hash_without_host = pair_int_hash(origin.scheme().hash(), origin.port());
if (origin.host().has<Empty>())
return hash_without_host;
return pair_int_hash(hash_without_host, URL::Parser::serialize_host(origin.host()).release_value_but_fixme_should_propagate_errors().hash());
}
};
} // namespace AK
namespace IPC {
template<>
ErrorOr<void> encode(Encoder&, Web::HTML::Origin const&);
template<>
ErrorOr<Web::HTML::Origin> decode(Decoder&);
}