diff options
Diffstat (limited to 'Userland/Services/WebContent')
-rw-r--r-- | Userland/Services/WebContent/CMakeLists.txt | 13 | ||||
-rw-r--r-- | Userland/Services/WebContent/ClientConnection.cpp | 169 | ||||
-rw-r--r-- | Userland/Services/WebContent/ClientConnection.h | 76 | ||||
-rw-r--r-- | Userland/Services/WebContent/Documentation.txt | 27 | ||||
-rw-r--r-- | Userland/Services/WebContent/Forward.h | 34 | ||||
-rw-r--r-- | Userland/Services/WebContent/PageHost.cpp | 182 | ||||
-rw-r--r-- | Userland/Services/WebContent/PageHost.h | 79 | ||||
-rw-r--r-- | Userland/Services/WebContent/WebContentClient.ipc | 18 | ||||
-rw-r--r-- | Userland/Services/WebContent/WebContentServer.ipc | 18 | ||||
-rw-r--r-- | Userland/Services/WebContent/main.cpp | 60 |
10 files changed, 676 insertions, 0 deletions
diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt new file mode 100644 index 0000000000..a7e367ff94 --- /dev/null +++ b/Userland/Services/WebContent/CMakeLists.txt @@ -0,0 +1,13 @@ +compile_ipc(WebContentServer.ipc WebContentServerEndpoint.h) +compile_ipc(WebContentClient.ipc WebContentClientEndpoint.h) + +set(SOURCES + ClientConnection.cpp + main.cpp + PageHost.cpp + WebContentServerEndpoint.h + WebContentClientEndpoint.h +) + +serenity_bin(WebContent) +target_link_libraries(WebContent LibCore LibIPC LibGfx LibWeb) diff --git a/Userland/Services/WebContent/ClientConnection.cpp b/Userland/Services/WebContent/ClientConnection.cpp new file mode 100644 index 0000000000..46b38f440b --- /dev/null +++ b/Userland/Services/WebContent/ClientConnection.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <AK/Badge.h> +#include <AK/SharedBuffer.h> +#include <LibGfx/Bitmap.h> +#include <LibGfx/SystemTheme.h> +#include <WebContent/ClientConnection.h> +#include <WebContent/PageHost.h> +#include <WebContent/WebContentClientEndpoint.h> + +namespace WebContent { + +static HashMap<int, RefPtr<ClientConnection>> s_connections; + +ClientConnection::ClientConnection(NonnullRefPtr<Core::LocalSocket> socket, int client_id) + : IPC::ClientConnection<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket), client_id) + , m_page_host(PageHost::create(*this)) +{ + s_connections.set(client_id, *this); + m_paint_flush_timer = Core::Timer::create_single_shot(0, [this] { flush_pending_paint_requests(); }); +} + +ClientConnection::~ClientConnection() +{ +} + +void ClientConnection::die() +{ + s_connections.remove(client_id()); + if (s_connections.is_empty()) + Core::EventLoop::current().quit(0); +} + +Web::Page& ClientConnection::page() +{ + return m_page_host->page(); +} + +const Web::Page& ClientConnection::page() const +{ + return m_page_host->page(); +} + +OwnPtr<Messages::WebContentServer::GreetResponse> ClientConnection::handle(const Messages::WebContentServer::Greet& message) +{ + set_client_pid(message.client_pid()); + return make<Messages::WebContentServer::GreetResponse>(client_id(), getpid()); +} + +void ClientConnection::handle(const Messages::WebContentServer::UpdateSystemTheme& message) +{ + auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); + if (!shared_buffer) { + dbgln("WebContentServer::UpdateSystemTheme: SharedBuffer already gone! Ignoring :^)"); + return; + } + Gfx::set_system_theme(*shared_buffer); + auto impl = Gfx::PaletteImpl::create_with_shared_buffer(*shared_buffer); + m_page_host->set_palette_impl(*impl); +} + +void ClientConnection::handle(const Messages::WebContentServer::LoadURL& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentServer::LoadURL: url=" << message.url(); +#endif + page().load(message.url()); +} + +void ClientConnection::handle(const Messages::WebContentServer::LoadHTML& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentServer::LoadHTML: html=" << message.html() << ", url=" << message.url(); +#endif + page().load_html(message.html(), message.url()); +} + +void ClientConnection::handle(const Messages::WebContentServer::SetViewportRect& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentServer::SetViewportRect: rect=" << message.rect(); +#endif + m_page_host->set_viewport_rect(message.rect()); +} + +void ClientConnection::handle(const Messages::WebContentServer::Paint& message) +{ +#ifdef DEBUG_SPAM + dbg() << "handle: WebContentServer::Paint: content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); +#endif + + for (auto& pending_paint : m_pending_paint_requests) { + if (pending_paint.bitmap->shbuf_id() == message.shbuf_id()) { + pending_paint.content_rect = message.content_rect(); + return; + } + } + + auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); + if (!shared_buffer) { +#ifdef DEBUG_SPAM + dbgln("WebContentServer::Paint: SharedBuffer already gone! Ignoring :^)"); +#endif + return; + } + auto shared_bitmap = Gfx::Bitmap::create_with_shared_buffer(Gfx::BitmapFormat::RGB32, shared_buffer.release_nonnull(), message.content_rect().size()); + if (!shared_bitmap) { + did_misbehave("WebContentServer::Paint: Cannot create Gfx::Bitmap wrapper around SharedBuffer"); + return; + } + + m_pending_paint_requests.append({ message.content_rect(), shared_bitmap.release_nonnull() }); + m_paint_flush_timer->start(); +} + +void ClientConnection::flush_pending_paint_requests() +{ + for (auto& pending_paint : m_pending_paint_requests) { + m_page_host->paint(pending_paint.content_rect, *pending_paint.bitmap); + post_message(Messages::WebContentClient::DidPaint(pending_paint.content_rect, pending_paint.bitmap->shbuf_id())); + } + m_pending_paint_requests.clear(); +} + +void ClientConnection::handle(const Messages::WebContentServer::MouseDown& message) +{ + page().handle_mousedown(message.position(), message.button(), message.modifiers()); +} + +void ClientConnection::handle(const Messages::WebContentServer::MouseMove& message) +{ + page().handle_mousemove(message.position(), message.buttons(), message.modifiers()); +} + +void ClientConnection::handle(const Messages::WebContentServer::MouseUp& message) +{ + page().handle_mouseup(message.position(), message.button(), message.modifiers()); +} + +void ClientConnection::handle(const Messages::WebContentServer::KeyDown& message) +{ + page().handle_keydown((KeyCode)message.key(), message.modifiers(), message.code_point()); +} + +} diff --git a/Userland/Services/WebContent/ClientConnection.h b/Userland/Services/WebContent/ClientConnection.h new file mode 100644 index 0000000000..42e2ab8313 --- /dev/null +++ b/Userland/Services/WebContent/ClientConnection.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <AK/HashMap.h> +#include <LibIPC/ClientConnection.h> +#include <LibWeb/Forward.h> +#include <WebContent/Forward.h> +#include <WebContent/WebContentClientEndpoint.h> +#include <WebContent/WebContentServerEndpoint.h> + +namespace WebContent { + +class ClientConnection final + : public IPC::ClientConnection<WebContentClientEndpoint, WebContentServerEndpoint> + , public WebContentServerEndpoint { + C_OBJECT(ClientConnection); + +public: + explicit ClientConnection(NonnullRefPtr<Core::LocalSocket>, int client_id); + ~ClientConnection() override; + + virtual void die() override; + +private: + Web::Page& page(); + const Web::Page& page() const; + + virtual OwnPtr<Messages::WebContentServer::GreetResponse> handle(const Messages::WebContentServer::Greet&) override; + virtual void handle(const Messages::WebContentServer::UpdateSystemTheme&) override; + virtual void handle(const Messages::WebContentServer::LoadURL&) override; + virtual void handle(const Messages::WebContentServer::LoadHTML&) override; + virtual void handle(const Messages::WebContentServer::Paint&) override; + virtual void handle(const Messages::WebContentServer::SetViewportRect&) override; + virtual void handle(const Messages::WebContentServer::MouseDown&) override; + virtual void handle(const Messages::WebContentServer::MouseMove&) override; + virtual void handle(const Messages::WebContentServer::MouseUp&) override; + virtual void handle(const Messages::WebContentServer::KeyDown&) override; + + void flush_pending_paint_requests(); + + NonnullOwnPtr<PageHost> m_page_host; + + struct PaintRequest { + Gfx::IntRect content_rect; + NonnullRefPtr<Gfx::Bitmap> bitmap; + }; + Vector<PaintRequest> m_pending_paint_requests; + RefPtr<Core::Timer> m_paint_flush_timer; +}; + +} diff --git a/Userland/Services/WebContent/Documentation.txt b/Userland/Services/WebContent/Documentation.txt new file mode 100644 index 0000000000..e82190106a --- /dev/null +++ b/Userland/Services/WebContent/Documentation.txt @@ -0,0 +1,27 @@ +===================== +Multi-process model: +===================== + +Server Client + +WebContent GUI process (OutOfProcessWebView embedder) + + OutOfProcessWebView (this is a GUI::Widget) +WebContent::ClientConnection <---> WebContentClient + WebContent::PageHost (Web::PageClient) + Web::Page + Web::Frame + Web::Document + .. + + +===================== +Single process model: +===================== + +Web::InProcessWebView (this is a GUI::Widget, and also a Web::PageClient) + Web::Page + Web::Frame + Web::Document + .. + diff --git a/Userland/Services/WebContent/Forward.h b/Userland/Services/WebContent/Forward.h new file mode 100644 index 0000000000..e43ca83960 --- /dev/null +++ b/Userland/Services/WebContent/Forward.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +namespace WebContent { + +class ClientConnection; +class PageHost; + +} diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp new file mode 100644 index 0000000000..11641235eb --- /dev/null +++ b/Userland/Services/WebContent/PageHost.cpp @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "PageHost.h" +#include "ClientConnection.h" +#include <AK/SharedBuffer.h> +#include <LibGfx/Painter.h> +#include <LibGfx/SystemTheme.h> +#include <LibWeb/Layout/InitialContainingBlockBox.h> +#include <LibWeb/Page/Frame.h> +#include <WebContent/WebContentClientEndpoint.h> + +namespace WebContent { + +PageHost::PageHost(ClientConnection& client) + : m_client(client) + , m_page(make<Web::Page>(*this)) +{ + setup_palette(); +} + +PageHost::~PageHost() +{ +} + +void PageHost::setup_palette() +{ + // FIXME: Get the proper palette from our peer somehow + auto buffer = SharedBuffer::create_with_size(sizeof(Gfx::SystemTheme)); + auto* theme = buffer->data<Gfx::SystemTheme>(); + theme->color[(int)Gfx::ColorRole::Window] = Color::Magenta; + theme->color[(int)Gfx::ColorRole::WindowText] = Color::Cyan; + m_palette_impl = Gfx::PaletteImpl::create_with_shared_buffer(*buffer); +} + +Gfx::Palette PageHost::palette() const +{ + return Gfx::Palette(*m_palette_impl); +} + +void PageHost::set_palette_impl(const Gfx::PaletteImpl& impl) +{ + m_palette_impl = impl; +} + +Web::Layout::InitialContainingBlockBox* PageHost::layout_root() +{ + auto* document = page().main_frame().document(); + if (!document) + return nullptr; + return document->layout_node(); +} + +void PageHost::paint(const Gfx::IntRect& content_rect, Gfx::Bitmap& target) +{ + Gfx::Painter painter(target); + Gfx::IntRect bitmap_rect { {}, content_rect.size() }; + + auto* layout_root = this->layout_root(); + if (!layout_root) { + painter.fill_rect(bitmap_rect, Color::White); + return; + } + + painter.fill_rect(bitmap_rect, layout_root->document().background_color(palette())); + + if (auto background_bitmap = layout_root->document().background_image()) { + painter.draw_tiled_bitmap(bitmap_rect, *background_bitmap); + } + + painter.translate(-content_rect.x(), -content_rect.y()); + + Web::PaintContext context(painter, palette(), Gfx::IntPoint()); + context.set_viewport_rect(content_rect); + layout_root->paint_all_phases(context); +} + +void PageHost::set_viewport_rect(const Gfx::IntRect& rect) +{ + page().main_frame().set_size(rect.size()); + if (page().main_frame().document()) + page().main_frame().document()->update_layout(); + page().main_frame().set_viewport_scroll_offset(rect.location()); +} + +void PageHost::page_did_invalidate(const Gfx::IntRect& content_rect) +{ + m_client.post_message(Messages::WebContentClient::DidInvalidateContentRect(content_rect)); +} + +void PageHost::page_did_change_selection() +{ + m_client.post_message(Messages::WebContentClient::DidChangeSelection()); +} + +void PageHost::page_did_layout() +{ + auto* layout_root = this->layout_root(); + ASSERT(layout_root); + auto content_size = enclosing_int_rect(layout_root->absolute_rect()).size(); + m_client.post_message(Messages::WebContentClient::DidLayout(content_size)); +} + +void PageHost::page_did_change_title(const String& title) +{ + m_client.post_message(Messages::WebContentClient::DidChangeTitle(title)); +} + +void PageHost::page_did_request_scroll_into_view(const Gfx::IntRect& rect) +{ + m_client.post_message(Messages::WebContentClient::DidRequestScrollIntoView(rect)); +} + +void PageHost::page_did_hover_link(const URL& url) +{ + m_client.post_message(Messages::WebContentClient::DidHoverLink(url)); +} + +void PageHost::page_did_unhover_link() +{ + m_client.post_message(Messages::WebContentClient::DidUnhoverLink()); +} + +void PageHost::page_did_click_link(const URL& url, const String& target, unsigned modifiers) +{ + m_client.post_message(Messages::WebContentClient::DidClickLink(url, target, modifiers)); +} + +void PageHost::page_did_middle_click_link(const URL& url, [[maybe_unused]] const String& target, [[maybe_unused]] unsigned modifiers) +{ + m_client.post_message(Messages::WebContentClient::DidMiddleClickLink(url, target, modifiers)); +} + +void PageHost::page_did_start_loading(const URL& url) +{ + m_client.post_message(Messages::WebContentClient::DidStartLoading(url)); +} + +void PageHost::page_did_finish_loading(const URL& url) +{ + m_client.post_message(Messages::WebContentClient::DidFinishLoading(url)); +} + +void PageHost::page_did_request_context_menu(const Gfx::IntPoint& content_position) +{ + m_client.post_message(Messages::WebContentClient::DidRequestContextMenu(content_position)); +} + +void PageHost::page_did_request_link_context_menu(const Gfx::IntPoint& content_position, const URL& url, const String& target, unsigned modifiers) +{ + m_client.post_message(Messages::WebContentClient::DidRequestLinkContextMenu(content_position, url, target, modifiers)); +} + +void PageHost::page_did_request_alert(const String& message) +{ + m_client.send_sync<Messages::WebContentClient::DidRequestAlert>(message); +} + +} diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h new file mode 100644 index 0000000000..0ee9e393d9 --- /dev/null +++ b/Userland/Services/WebContent/PageHost.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include <LibWeb/Page/Page.h> + +namespace WebContent { + +class ClientConnection; + +class PageHost final : public Web::PageClient { + AK_MAKE_NONCOPYABLE(PageHost); + AK_MAKE_NONMOVABLE(PageHost); + +public: + static NonnullOwnPtr<PageHost> create(ClientConnection& client) { return adopt_own(*new PageHost(client)); } + virtual ~PageHost(); + + Web::Page& page() { return *m_page; } + const Web::Page& page() const { return *m_page; } + + void paint(const Gfx::IntRect& content_rect, Gfx::Bitmap&); + + void set_palette_impl(const Gfx::PaletteImpl&); + void set_viewport_rect(const Gfx::IntRect&); + +private: + // ^PageClient + virtual Gfx::Palette palette() const override; + virtual void page_did_invalidate(const Gfx::IntRect&) override; + virtual void page_did_change_selection() override; + virtual void page_did_layout() override; + virtual void page_did_change_title(const String&) override; + virtual void page_did_request_scroll_into_view(const Gfx::IntRect&) override; + virtual void page_did_hover_link(const URL&) override; + virtual void page_did_unhover_link() override; + virtual void page_did_click_link(const URL&, const String& target, unsigned modifiers) override; + virtual void page_did_middle_click_link(const URL&, const String& target, unsigned modifiers) override; + virtual void page_did_request_context_menu(const Gfx::IntPoint&) override; + virtual void page_did_request_link_context_menu(const Gfx::IntPoint&, const URL&, const String& target, unsigned modifiers) override; + virtual void page_did_start_loading(const URL&) override; + virtual void page_did_finish_loading(const URL&) override; + virtual void page_did_request_alert(const String&) override; + + explicit PageHost(ClientConnection&); + + Web::Layout::InitialContainingBlockBox* layout_root(); + void setup_palette(); + + ClientConnection& m_client; + NonnullOwnPtr<Web::Page> m_page; + RefPtr<Gfx::PaletteImpl> m_palette_impl; +}; + +} diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc new file mode 100644 index 0000000000..10008a765c --- /dev/null +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -0,0 +1,18 @@ +endpoint WebContentClient = 90 +{ + DidStartLoading(URL url) =| + DidFinishLoading(URL url) =| + DidPaint(Gfx::IntRect content_rect, i32 shbuf_id) =| + DidInvalidateContentRect(Gfx::IntRect content_rect) =| + DidChangeSelection() =| + DidLayout(Gfx::IntSize content_size) =| + DidChangeTitle(String title) =| + DidRequestScrollIntoView(Gfx::IntRect rect) =| + DidHoverLink(URL url) =| + DidUnhoverLink() =| + DidClickLink(URL url, String target, unsigned modifiers) =| + DidMiddleClickLink(URL url, String target, unsigned modifiers) =| + DidRequestContextMenu(Gfx::IntPoint content_position) =| + DidRequestLinkContextMenu(Gfx::IntPoint content_position, URL url, String target, unsigned modifiers) =| + DidRequestAlert(String message) => () +} diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc new file mode 100644 index 0000000000..143650dab7 --- /dev/null +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -0,0 +1,18 @@ +endpoint WebContentServer = 89 +{ + Greet(i32 client_pid) => (i32 client_id, i32 server_pid) + + UpdateSystemTheme(i32 shbuf_id) =| + + LoadURL(URL url) =| + LoadHTML(String html, URL url) =| + + Paint(Gfx::IntRect content_rect, i32 shbuf_id) =| + SetViewportRect(Gfx::IntRect rect) =| + + MouseDown(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =| + MouseMove(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =| + MouseUp(Gfx::IntPoint position, unsigned button, unsigned buttons, unsigned modifiers) =| + + KeyDown(i32 key, unsigned modifiers, u32 code_point) =| +} diff --git a/Userland/Services/WebContent/main.cpp b/Userland/Services/WebContent/main.cpp new file mode 100644 index 0000000000..5367f2cce3 --- /dev/null +++ b/Userland/Services/WebContent/main.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <LibCore/EventLoop.h> +#include <LibCore/LocalServer.h> +#include <LibIPC/ClientConnection.h> +#include <WebContent/ClientConnection.h> + +int main(int, char**) +{ + Core::EventLoop event_loop; + if (pledge("stdio shared_buffer accept unix rpath recvfd", nullptr) < 0) { + perror("pledge"); + return 1; + } + if (unveil("/res", "r") < 0) { + perror("unveil"); + return 1; + } + if (unveil("/tmp/portal/protocol", "rw") < 0) { + perror("unveil"); + return 1; + } + if (unveil("/tmp/portal/image", "rw") < 0) { + perror("unveil"); + return 1; + } + if (unveil(nullptr, nullptr) < 0) { + perror("unveil"); + return 1; + } + + auto socket = Core::LocalSocket::take_over_accepted_socket_from_system_server(); + ASSERT(socket); + IPC::new_client_connection<WebContent::ClientConnection>(socket.release_nonnull(), 1); + return event_loop.exec(); +} |