ladybird/Libraries/LibIPC/Decoder.cpp
Shannon Booth 89dbdd3411 LibURL: Add domain concept to URL::Origin to fix same-origin-domain
The same-origin domain check always returned true if only the scheme
matched. This was because of missing steps to check for the origin's
domain, which didn't exist. Add this concept to URL::Origin, even
though we do not use it at this stage in document.domain setter.

Co-Authored-By: Luke Wilde <luke@ladybird.org>
2025-12-30 13:02:10 +01:00

177 lines
4.4 KiB
C++

/*
* Copyright (c) 2020, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2023-2025, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/JsonValue.h>
#include <AK/NumericLimits.h>
#include <AK/Utf16String.h>
#include <LibCore/AnonymousBuffer.h>
#include <LibCore/Proxy.h>
#include <LibCore/Socket.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/File.h>
#include <LibURL/Parser.h>
#include <LibURL/URL.h>
namespace IPC {
ErrorOr<size_t> Decoder::decode_size()
{
return static_cast<size_t>(TRY(decode<u32>()));
}
template<>
ErrorOr<String> decode(Decoder& decoder)
{
auto length = TRY(decoder.decode_size());
return String::from_stream(decoder.stream(), length);
}
template<>
ErrorOr<Utf16String> decode(Decoder& decoder)
{
auto is_ascii = TRY(decoder.decode<bool>());
auto length_in_code_units = TRY(decoder.decode_size());
return Utf16String::from_ipc_stream(decoder.stream(), length_in_code_units, is_ascii);
}
template<>
ErrorOr<ByteString> decode(Decoder& decoder)
{
auto length = TRY(decoder.decode_size());
if (length == 0)
return ByteString::empty();
return ByteString::create_and_overwrite(length, [&](Bytes bytes) -> ErrorOr<void> {
TRY(decoder.decode_into(bytes));
return {};
});
}
template<>
ErrorOr<ByteBuffer> decode(Decoder& decoder)
{
auto length = TRY(decoder.decode_size());
if (length == 0)
return ByteBuffer {};
auto buffer = TRY(ByteBuffer::create_uninitialized(length));
auto bytes = buffer.bytes();
TRY(decoder.decode_into(bytes));
return buffer;
}
template<>
ErrorOr<JsonValue> decode(Decoder& decoder)
{
auto json = TRY(decoder.decode<ByteString>());
return JsonValue::from_string(json);
}
template<>
ErrorOr<AK::Duration> decode(Decoder& decoder)
{
auto nanoseconds = TRY(decoder.decode<i64>());
return AK::Duration::from_nanoseconds(nanoseconds);
}
template<>
ErrorOr<UnixDateTime> decode(Decoder& decoder)
{
auto nanoseconds = TRY(decoder.decode<i64>());
return AK::UnixDateTime::from_nanoseconds_since_epoch(nanoseconds);
}
template<>
ErrorOr<URL::URL> decode(Decoder& decoder)
{
auto url_string = TRY(decoder.decode<ByteString>());
auto url = URL::Parser::basic_parse(url_string);
if (!url.has_value())
return Error::from_string_view("Failed to parse URL in IPC Decode"sv);
bool has_blob_url = TRY(decoder.decode<bool>());
if (!has_blob_url)
return url.release_value();
url->set_blob_url_entry(URL::BlobURLEntry {
.object = TRY(decoder.decode<URL::BlobURLEntry::Object>()),
.environment { .origin = TRY(decoder.decode<URL::Origin>()) },
});
return url.release_value();
}
template<>
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 scheme = TRY(decoder.decode<Optional<String>>());
auto host = TRY(decoder.decode<URL::Host>());
auto port = TRY(decoder.decode<Optional<u16>>());
auto domain = TRY(decoder.decode<Optional<String>>());
return URL::Origin { move(scheme), move(host), port, move(domain) };
}
template<>
ErrorOr<URL::Host> decode(Decoder& decoder)
{
auto value = TRY(decoder.decode<URL::Host::VariantType>());
return URL::Host { move(value) };
}
template<>
ErrorOr<Empty> decode(Decoder&)
{
return Empty {};
}
template<>
ErrorOr<Core::AnonymousBuffer> decode(Decoder& decoder)
{
if (auto valid = TRY(decoder.decode<bool>()); !valid)
return Core::AnonymousBuffer {};
auto size = TRY(decoder.decode_size());
auto anon_file = TRY(decoder.decode<IPC::File>());
return Core::AnonymousBuffer::create_from_anon_fd(anon_file.take_fd(), size);
}
template<>
ErrorOr<Core::ProxyData> decode(Decoder& decoder)
{
auto type = TRY(decoder.decode<Core::ProxyData::Type>());
auto host_ipv4 = TRY(decoder.decode<u32>());
auto port = TRY(decoder.decode<int>());
return Core::ProxyData { type, host_ipv4, port };
}
template<>
ErrorOr<URL::BlobURLEntry::Blob> decode<URL::BlobURLEntry::Blob>(Decoder& decoder)
{
return URL::BlobURLEntry::Blob {
.type = TRY(decoder.decode<String>()),
.data = TRY(decoder.decode<ByteBuffer>())
};
}
template<>
ErrorOr<URL::BlobURLEntry::MediaSource> decode<URL::BlobURLEntry::MediaSource>(Decoder&)
{
return URL::BlobURLEntry::MediaSource {};
}
}