diff --git a/Base/etc/SystemServer.ini b/Base/etc/SystemServer.ini index d81a5ccd41..9410994127 100644 --- a/Base/etc/SystemServer.ini +++ b/Base/etc/SystemServer.ini @@ -7,6 +7,13 @@ KeepAlive=1 User=protocol BootModes=text,graphical +[WebContent] +Socket=/tmp/portal/webcontent +SocketPermissions=660 +Lazy=1 +User=webcontent +BootModes=graphical + [LookupServer] Socket=/tmp/portal/lookup SocketPermissions=660 diff --git a/Base/etc/group b/Base/etc/group index 2fb7986f9c..5dd2b89ac3 100644 --- a/Base/etc/group +++ b/Base/etc/group @@ -4,8 +4,9 @@ tty:x:2: phys:x:3:window,anon audio:x:4:anon lookup:x:10:protocol,anon -protocol:x:11:anon +protocol:x:11:webcontent,anon notify:x:12:anon window:x:13:anon,notify clipboard:x:14:anon,notify +webcontent:x:15:anon users:x:100:anon diff --git a/Base/etc/passwd b/Base/etc/passwd index 814e0d6f96..d52852ce2c 100644 --- a/Base/etc/passwd +++ b/Base/etc/passwd @@ -4,5 +4,6 @@ protocol:x:11:11:ProtocolServer,,,:/:/bin/false notify:x:12:12:NotificationServer,,,:/:/bin/false window:x:13:13:WindowServer,,,:/:/bin/false clipboard:x:14:14:Clipboard,,,:/:/bin/false +webcontent:x:15:15:WebContent,,,:/:/bin/false anon:x:100:100:Anonymous,,,:/home/anon:/bin/sh nona:x:200:200:Nona,,,:/home/nona:/bin/sh diff --git a/Demos/CMakeLists.txt b/Demos/CMakeLists.txt index 65bc6fe9f6..e82271ba16 100644 --- a/Demos/CMakeLists.txt +++ b/Demos/CMakeLists.txt @@ -6,4 +6,5 @@ add_subdirectory(HelloWorld) add_subdirectory(LibGfxDemo) add_subdirectory(Mouse) add_subdirectory(Screensaver) +add_subdirectory(WebView) add_subdirectory(WidgetGallery) diff --git a/Demos/WebView/CMakeLists.txt b/Demos/WebView/CMakeLists.txt new file mode 100644 index 0000000000..cf139cff1a --- /dev/null +++ b/Demos/WebView/CMakeLists.txt @@ -0,0 +1,13 @@ +set(SOURCES + main.cpp + WebContentView.cpp + WebContentClient.cpp +) + +set(GENERATED_SOURCES + ../../Services/WebContent/WebContentClientEndpoint.h + ../../Services/WebContent/WebContentServerEndpoint.h +) + +serenity_bin(WebView) +target_link_libraries(WebView LibGUI) diff --git a/Demos/WebView/WebContentClient.cpp b/Demos/WebView/WebContentClient.cpp new file mode 100644 index 0000000000..1f2c847e09 --- /dev/null +++ b/Demos/WebView/WebContentClient.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 "WebContentClient.h" +#include "WebContentView.h" +#include + +WebContentClient::WebContentClient(WebContentView& view) + : IPC::ServerConnection(*this, "/tmp/portal/webcontent") + , m_view(view) +{ + handshake(); +} + +void WebContentClient::handshake() +{ + auto response = send_sync(); + set_my_client_id(response->client_id()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidPaint& message) +{ + dbg() << "handle: WebContentClient::DidPaint! content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); + m_view.notify_server_did_paint({}, message.shbuf_id()); +} + +void WebContentClient::handle(const Messages::WebContentClient::DidFinishLoad& message) +{ + dbg() << "handle: WebContentClient::DidFinishLoad! url=" << message.url(); +} diff --git a/Demos/WebView/WebContentClient.h b/Demos/WebView/WebContentClient.h new file mode 100644 index 0000000000..ed9e9b41f4 --- /dev/null +++ b/Demos/WebView/WebContentClient.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 +#include +#include +#include + +class WebContentView; + +class WebContentClient + : public IPC::ServerConnection + , public WebContentClientEndpoint { + C_OBJECT(WebContentClient); + +public: + virtual void handshake() override; + +private: + WebContentClient(WebContentView&); + + virtual void handle(const Messages::WebContentClient::DidPaint&) override; + virtual void handle(const Messages::WebContentClient::DidFinishLoad&) override; + + WebContentView& m_view; +}; diff --git a/Demos/WebView/WebContentView.cpp b/Demos/WebView/WebContentView.cpp new file mode 100644 index 0000000000..0cb87d5dae --- /dev/null +++ b/Demos/WebView/WebContentView.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 "WebContentView.h" +#include "WebContentClient.h" +#include +#include +#include + +WebContentView::WebContentView() +{ + m_client = WebContentClient::construct(*this); + client().post_message(Messages::WebContentServer::UpdateSystemTheme(Gfx::current_system_theme_buffer_id())); +} + +WebContentView::~WebContentView() +{ +} + +void WebContentView::load(const URL& url) +{ + client().post_message(Messages::WebContentServer::LoadURL(url)); +} + +void WebContentView::paint_event(GUI::PaintEvent& event) +{ + GUI::Painter painter(*this); + painter.add_clip_rect(event.rect()); + ASSERT(m_bitmap); + painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect()); +} + +void WebContentView::resize_event(GUI::ResizeEvent& event) +{ + GUI::Widget::resize_event(event); + auto bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGB32, event.size()); + m_bitmap = bitmap->to_bitmap_backed_by_shared_buffer(); + m_bitmap->shared_buffer()->share_with(client().server_pid()); + client().post_message(Messages::WebContentServer::SetViewportRect(Gfx::IntRect({ 0, 0 }, event.size()))); + client().post_message(Messages::WebContentServer::Paint(m_bitmap->rect(), m_bitmap->shbuf_id())); +} + +void WebContentView::notify_server_did_paint(Badge, i32 shbuf_id) +{ + if (m_bitmap->shbuf_id() == shbuf_id) + update(); +} + +WebContentClient& WebContentView::client() +{ + return *m_client; +} diff --git a/Demos/WebView/WebContentView.h b/Demos/WebView/WebContentView.h new file mode 100644 index 0000000000..353b9d9c02 --- /dev/null +++ b/Demos/WebView/WebContentView.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 + +class WebContentClient; + +class WebContentView final : public GUI::Widget { + C_OBJECT(WebContentView); + +public: + virtual ~WebContentView() override; + + void load(const URL&); + + void notify_server_did_paint(Badge, i32 shbuf_id); + +private: + WebContentView(); + + virtual void paint_event(GUI::PaintEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; + + WebContentClient& client(); + + RefPtr m_client; + RefPtr m_bitmap; +}; diff --git a/Demos/WebView/main.cpp b/Demos/WebView/main.cpp new file mode 100644 index 0000000000..9afac30fcc --- /dev/null +++ b/Demos/WebView/main.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 "WebContentView.h" +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + GUI::Application app(argc, argv); + auto window = GUI::Window::construct(); + auto& view = window->set_main_widget(); + window->set_title("WebContentView"); + window->set_rect(100, 100, 640, 480); + window->show(); + + view.load("file:///res/html/misc/welcome.html"); + + return app.exec(); +} diff --git a/Meta/build-root-filesystem.sh b/Meta/build-root-filesystem.sh index 597f4babcd..3b69b31e55 100755 --- a/Meta/build-root-filesystem.sh +++ b/Meta/build-root-filesystem.sh @@ -163,6 +163,7 @@ ln -s ProfileViewer mnt/bin/pv ln -s WebServer mnt/bin/ws ln -s KeyboardSettings mnt/bin/keymap ln -s Solitaire mnt/bin/sl +ln -s WebView mnt/bin/wv echo "done" # Run local sync script, if it exists diff --git a/Services/CMakeLists.txt b/Services/CMakeLists.txt index 61f03a3e92..364c7ea574 100644 --- a/Services/CMakeLists.txt +++ b/Services/CMakeLists.txt @@ -9,5 +9,6 @@ add_subdirectory(SystemMenu) add_subdirectory(SystemServer) add_subdirectory(Taskbar) add_subdirectory(TelnetServer) +add_subdirectory(WebContent) add_subdirectory(WebServer) add_subdirectory(WindowServer) diff --git a/Services/WebContent/CMakeLists.txt b/Services/WebContent/CMakeLists.txt new file mode 100644 index 0000000000..a7e367ff94 --- /dev/null +++ b/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/Services/WebContent/ClientConnection.cpp b/Services/WebContent/ClientConnection.cpp new file mode 100644 index 0000000000..d750f0968a --- /dev/null +++ b/Services/WebContent/ClientConnection.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 +#include +#include +#include +#include +#include +#include + +namespace WebContent { + +static HashMap> s_connections; + +ClientConnection::ClientConnection(Core::LocalSocket& socket, int client_id) + : IPC::ClientConnection(*this, socket, client_id) + , m_page_host(PageHost::create()) +{ + s_connections.set(client_id, *this); +} + +ClientConnection::~ClientConnection() +{ +} + +void ClientConnection::die() +{ + s_connections.remove(client_id()); +} + +Web::Page& ClientConnection::page() +{ + return m_page_host->page(); +} + +const Web::Page& ClientConnection::page() const +{ + return m_page_host->page(); +} + +OwnPtr ClientConnection::handle(const Messages::WebContentServer::Greet&) +{ + return make(client_id()); +} + +void ClientConnection::handle(const Messages::WebContentServer::UpdateSystemTheme& message) +{ + auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); + if (!shared_buffer) { + dbg() << "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) +{ + dbg() << "handle: WebContentServer::LoadURL: url=" << message.url(); + page().load(message.url()); +} + +void ClientConnection::handle(const Messages::WebContentServer::SetViewportRect& message) +{ + dbg() << "handle: WebContentServer::SetViewportRect: rect=" << message.rect(); + m_page_host->set_viewport_rect(message.rect()); +} + +void ClientConnection::handle(const Messages::WebContentServer::Paint& message) +{ + dbg() << "handle: WebContentServer::Paint: content_rect=" << message.content_rect() << ", shbuf_id=" << message.shbuf_id(); + + auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); + if (!shared_buffer) { + dbg() << "WebContentServer::Paint: SharedBuffer already gone! Ignoring :^)"; + 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_page_host->paint(message.content_rect(), *shared_bitmap); + post_message(Messages::WebContentClient::DidPaint(message.content_rect(), message.shbuf_id())); +} + +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()); +} + +} diff --git a/Services/WebContent/ClientConnection.h b/Services/WebContent/ClientConnection.h new file mode 100644 index 0000000000..5ee492132a --- /dev/null +++ b/Services/WebContent/ClientConnection.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * 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 +#include +#include +#include +#include + +namespace WebContent { + +class ClientConnection final + : public IPC::ClientConnection + , public WebContentServerEndpoint { + C_OBJECT(ClientConnection); + +public: + explicit ClientConnection(Core::LocalSocket&, int client_id); + ~ClientConnection() override; + + virtual void die() override; + +private: + Web::Page& page(); + const Web::Page& page() const; + + virtual OwnPtr 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::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; + + NonnullOwnPtr m_page_host; +}; + +} diff --git a/Services/WebContent/Forward.h b/Services/WebContent/Forward.h new file mode 100644 index 0000000000..e43ca83960 --- /dev/null +++ b/Services/WebContent/Forward.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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/Services/WebContent/PageHost.cpp b/Services/WebContent/PageHost.cpp new file mode 100644 index 0000000000..fdcf3e16c4 --- /dev/null +++ b/Services/WebContent/PageHost.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 +#include +#include +#include +#include + +namespace WebContent { + +PageHost::PageHost() + : m_page(make(*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 = (Gfx::SystemTheme*)buffer->data(); + 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; +} + +void PageHost::paint(const Gfx::IntRect& content_rect, Gfx::Bitmap& target) +{ + Gfx::Painter painter(target); + + auto* document = page().main_frame().document(); + if (!document) + return; + + auto* layout_root = document->layout_node(); + if (!layout_root) { + painter.fill_rect(content_rect, Color::White); + return; + } + + painter.fill_rect(content_rect, document->background_color(palette())); + + if (auto background_bitmap = document->background_image()) { + painter.draw_tiled_bitmap(content_rect, *background_bitmap); + } + + Web::RenderingContext context(painter, palette(), Gfx::IntPoint()); + context.set_viewport_rect(content_rect); + layout_root->render(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()->layout(); + page().main_frame().set_viewport_rect(rect); +} + +} diff --git a/Services/WebContent/PageHost.h b/Services/WebContent/PageHost.h new file mode 100644 index 0000000000..dd9908b94e --- /dev/null +++ b/Services/WebContent/PageHost.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 + +namespace WebContent { + +class PageHost : public Web::PageClient { + AK_MAKE_NONCOPYABLE(PageHost); + AK_MAKE_NONMOVABLE(PageHost); + +public: + static NonnullOwnPtr create() { return adopt_own(*new PageHost); } + 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: + PageHost(); + + Gfx::Palette palette() const; + void setup_palette(); + + NonnullOwnPtr m_page; + RefPtr m_palette_impl; +}; + +} diff --git a/Services/WebContent/WebContentClient.ipc b/Services/WebContent/WebContentClient.ipc new file mode 100644 index 0000000000..6229838332 --- /dev/null +++ b/Services/WebContent/WebContentClient.ipc @@ -0,0 +1,6 @@ +endpoint WebContentClient = 90 +{ + DidFinishLoad(URL url) =| + + DidPaint(Gfx::IntRect content_rect, i32 shbuf_id) =| +} diff --git a/Services/WebContent/WebContentServer.ipc b/Services/WebContent/WebContentServer.ipc new file mode 100644 index 0000000000..d398fbb1b7 --- /dev/null +++ b/Services/WebContent/WebContentServer.ipc @@ -0,0 +1,15 @@ +endpoint WebContentServer = 89 +{ + Greet() => (i32 client_id) + + UpdateSystemTheme(i32 shbuf_id) =| + + LoadURL(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) =| +} diff --git a/Services/WebContent/main.cpp b/Services/WebContent/main.cpp new file mode 100644 index 0000000000..877da897aa --- /dev/null +++ b/Services/WebContent/main.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020, Andreas Kling + * 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 +#include +#include +#include + +int main(int, char**) +{ + Core::EventLoop event_loop; + if (pledge("stdio shared_buffer accept unix rpath", 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(nullptr, nullptr) < 0) { + perror("unveil"); + return 1; + } + + auto server = Core::LocalServer::construct(); + bool ok = server->take_over_from_system_server(); + ASSERT(ok); + server->on_ready_to_accept = [&] { + auto client_socket = server->accept(); + if (!client_socket) { + dbg() << "WebContent: accept failed."; + return; + } + static int s_next_client_id = 0; + int client_id = ++s_next_client_id; + IPC::new_client_connection(*client_socket, client_id); + }; + return event_loop.exec(); +}