diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index cf84ad68be..c34632302a 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -377,7 +377,7 @@ set(GENERATED_SOURCES ) serenity_lib(LibWeb web) -target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibProtocol LibImageDecoderClient LibWasm LibXML) +target_link_libraries(LibWeb LibCore LibJS LibMarkdown LibGemini LibGUI LibGfx LibTextCodec LibProtocol LibWasm LibXML) link_with_unicode_data(LibWeb) generate_js_wrappers(LibWeb) diff --git a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp index 03680401c8..5684d6a70b 100644 --- a/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp +++ b/Userland/Libraries/LibWeb/HTML/HTMLLinkElement.cpp @@ -155,7 +155,7 @@ bool HTMLLinkElement::load_favicon_and_use_if_window_is_active() return false; RefPtr favicon_bitmap; - auto decoded_image = Web::image_decoder_client().decode_image(resource()->encoded_data()); + auto decoded_image = Web::ImageDecoding::Decoder::the().decode_image(resource()->encoded_data()); if (!decoded_image.has_value() || decoded_image->frames.is_empty()) { dbgln("Could not decode favicon {}", resource()->url()); return false; diff --git a/Userland/Libraries/LibWeb/ImageDecoding.cpp b/Userland/Libraries/LibWeb/ImageDecoding.cpp index 44967a8860..fc2aefee4e 100644 --- a/Userland/Libraries/LibWeb/ImageDecoding.cpp +++ b/Userland/Libraries/LibWeb/ImageDecoding.cpp @@ -1,23 +1,32 @@ /* * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2022, Dex♪ * * SPDX-License-Identifier: BSD-2-Clause */ #include -namespace Web { +namespace Web::ImageDecoding { -ImageDecoderClient::Client& image_decoder_client() +static RefPtr s_decoder; + +Decoder::Decoder() = default; + +Decoder::~Decoder() = default; + +void Decoder::initialize(RefPtr&& decoder) { - static RefPtr image_decoder_client; - if (!image_decoder_client) { - image_decoder_client = ImageDecoderClient::Client::try_create().release_value_but_fixme_should_propagate_errors(); - image_decoder_client->on_death = [&] { - image_decoder_client = nullptr; - }; + s_decoder = move(decoder); +} + +Decoder& Decoder::the() +{ + if (!s_decoder) [[unlikely]] { + dbgln("Web::ImageDecoding::Decoder was not initialized!"); + VERIFY_NOT_REACHED(); } - return *image_decoder_client; + return *s_decoder; } } diff --git a/Userland/Libraries/LibWeb/ImageDecoding.h b/Userland/Libraries/LibWeb/ImageDecoding.h index 081b4e123c..2c462aae2c 100644 --- a/Userland/Libraries/LibWeb/ImageDecoding.h +++ b/Userland/Libraries/LibWeb/ImageDecoding.h @@ -1,15 +1,40 @@ /* * Copyright (c) 2020-2021, Andreas Kling + * Copyright (c) 2022, Dex♪ * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include +#include +#include +#include -namespace Web { +namespace Web::ImageDecoding { -ImageDecoderClient::Client& image_decoder_client(); +struct Frame { + RefPtr bitmap; + size_t duration { 0 }; +}; + +struct DecodedImage { + bool is_animated { false }; + u32 loop_count { 0 }; + Vector frames; +}; + +class Decoder : public RefCounted { +public: + virtual ~Decoder(); + + static void initialize(RefPtr&&); + static Decoder& the(); + + virtual Optional decode_image(ReadonlyBytes) = 0; + +protected: + explicit Decoder(); +}; } diff --git a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp index 1b54366e0b..6defe4cb2a 100644 --- a/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp +++ b/Userland/Libraries/LibWeb/Loader/FrameLoader.cpp @@ -75,8 +75,7 @@ static bool build_text_document(DOM::Document& document, ByteBuffer const& data) static bool build_image_document(DOM::Document& document, ByteBuffer const& data) { - NonnullRefPtr decoder = image_decoder_client(); - auto image = decoder->decode_image(data); + auto image = ImageDecoding::Decoder::the().decode_image(data); if (!image.has_value() || image->frames.is_empty()) return false; auto const& frame = image->frames[0]; @@ -209,7 +208,7 @@ bool FrameLoader::load(LoadRequest& request, Type type) if (data.is_empty()) return; RefPtr favicon_bitmap; - auto decoded_image = image_decoder_client().decode_image(data); + auto decoded_image = ImageDecoding::Decoder::the().decode_image(data); if (!decoded_image.has_value() || decoded_image->frames.is_empty()) { dbgln("Could not decode favicon {}", favicon_url); } else { diff --git a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp b/Userland/Libraries/LibWeb/Loader/ImageResource.cpp index 874f4d4ee4..ac2704f4c4 100644 --- a/Userland/Libraries/LibWeb/Loader/ImageResource.cpp +++ b/Userland/Libraries/LibWeb/Loader/ImageResource.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -46,8 +47,7 @@ void ImageResource::decode_if_needed() const if (!m_decoded_frames.is_empty()) return; - NonnullRefPtr decoder = image_decoder_client(); - auto image = decoder->decode_image(encoded_data()); + auto image = ImageDecoding::Decoder::the().decode_image(encoded_data()); if (image.has_value()) { m_loop_count = image.value().loop_count; diff --git a/Userland/Libraries/LibWebView/CMakeLists.txt b/Userland/Libraries/LibWebView/CMakeLists.txt index 5a62bbc5a9..d0da3aef1e 100644 --- a/Userland/Libraries/LibWebView/CMakeLists.txt +++ b/Userland/Libraries/LibWebView/CMakeLists.txt @@ -1,5 +1,6 @@ set(SOURCES DOMTreeModel.cpp + ImageDecoderClientAdapter.cpp OutOfProcessWebView.cpp StylePropertiesModel.cpp WebContentClient.cpp @@ -13,6 +14,6 @@ set(GENERATED_SOURCES ) serenity_lib(LibWebView webview) -target_link_libraries(LibWebView LibGfx LibGUI LibIPC LibWeb) +target_link_libraries(LibWebView LibGfx LibGUI LibImageDecoderClient LibIPC LibWeb) add_subdirectory(DumpLayoutTree) diff --git a/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.cpp b/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.cpp new file mode 100644 index 0000000000..47fa6e1878 --- /dev/null +++ b/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include + +namespace WebView { + +NonnullRefPtr ImageDecoderClientAdapter::create() +{ + return adopt_ref(*new ImageDecoderClientAdapter()); +} + +Optional ImageDecoderClientAdapter::decode_image(ReadonlyBytes bytes) +{ + if (!m_client) { + m_client = ImageDecoderClient::Client::try_create().release_value_but_fixme_should_propagate_errors(); + m_client->on_death = [&] { + m_client = nullptr; + }; + } + + auto result_or_empty = m_client->decode_image(bytes); + if (!result_or_empty.has_value()) + return {}; + auto result = result_or_empty.release_value(); + + Web::ImageDecoding::DecodedImage decoded_image; + decoded_image.is_animated = result.is_animated; + decoded_image.loop_count = result.loop_count; + for (auto const& frame : result.frames) { + decoded_image.frames.empend(move(frame.bitmap), frame.duration); + } + + return decoded_image; +} + +} diff --git a/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.h b/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.h new file mode 100644 index 0000000000..e46b0e6974 --- /dev/null +++ b/Userland/Libraries/LibWebView/ImageDecoderClientAdapter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022, Dex♪ + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace ImageDecoderClient { +class Client; +} + +namespace WebView { + +class ImageDecoderClientAdapter : public Web::ImageDecoding::Decoder { +public: + static NonnullRefPtr create(); + + virtual ~ImageDecoderClientAdapter() override = default; + + virtual Optional decode_image(ReadonlyBytes) override; + +private: + explicit ImageDecoderClientAdapter() = default; + + RefPtr m_client; +}; + +} diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index a0f329fc97..aaa5c67138 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -1,6 +1,7 @@ #include #include #include +#include endpoint WebContentClient { diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp index 351fd4b159..42c5292dd9 100644 --- a/Userland/Services/WebContent/main.cpp +++ b/Userland/Services/WebContent/main.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include ErrorOr serenity_main(Main::Arguments) @@ -22,6 +24,8 @@ ErrorOr serenity_main(Main::Arguments) TRY(Core::System::unveil("/tmp/portal/websocket", "rw")); TRY(Core::System::unveil(nullptr, nullptr)); + Web::ImageDecoding::Decoder::initialize(WebView::ImageDecoderClientAdapter::create()); + auto client = TRY(IPC::take_over_accepted_client_from_system_server()); return event_loop.exec(); }