diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp index 282749090c..ba4cb6d03b 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.cpp @@ -41,14 +41,40 @@ OutOfProcessWebView::OutOfProcessWebView() { set_should_hide_unnecessary_scrollbars(true); set_focus_policy(GUI::FocusPolicy::StrongFocus); - m_client = WebContentClient::construct(*this); - client().post_message(Messages::WebContentServer::UpdateSystemTheme(Gfx::current_system_theme_buffer())); + + create_client(); } OutOfProcessWebView::~OutOfProcessWebView() { } +void OutOfProcessWebView::create_client() +{ + m_client_state = {}; + + m_client_state.client = WebContentClient::construct(*this); + m_client_state.client->on_web_content_process_crash = [this] { + create_client(); + ASSERT(m_client_state.client); + handle_resize(); + StringBuilder builder; + builder.append("Crashed: "); + builder.append(m_url.to_string()); + builder.append(""); + builder.append("

Web page crashed"); + if (!m_url.host().is_empty()) { + builder.appendff(" on {}", m_url.host()); + } + builder.append("

"); + builder.appendff("The web page {} has crashed.

You can reload the page to try again.", m_url, m_url); + builder.append(""); + load_html(builder.to_string(), m_url); + }; + + client().post_message(Messages::WebContentServer::UpdateSystemTheme(Gfx::current_system_theme_buffer())); +} + void OutOfProcessWebView::load(const URL& url) { m_url = url; @@ -78,7 +104,7 @@ void OutOfProcessWebView::paint_event(GUI::PaintEvent& event) GUI::Painter painter(*this); painter.add_clip_rect(event.rect()); - if (!m_has_usable_bitmap) { + if (!m_client_state.has_usable_bitmap) { painter.fill_rect(frame_inner_rect(), palette().base()); return; } @@ -86,43 +112,47 @@ void OutOfProcessWebView::paint_event(GUI::PaintEvent& event) painter.add_clip_rect(frame_inner_rect()); painter.translate(frame_thickness(), frame_thickness()); - ASSERT(m_front_bitmap); - painter.blit({ 0, 0 }, *m_front_bitmap, m_front_bitmap->rect()); + ASSERT(m_client_state.front_bitmap); + painter.blit({ 0, 0 }, *m_client_state.front_bitmap, m_client_state.front_bitmap->rect()); } void OutOfProcessWebView::resize_event(GUI::ResizeEvent& event) { GUI::ScrollableWidget::resize_event(event); + handle_resize(); +} +void OutOfProcessWebView::handle_resize() +{ client().post_message(Messages::WebContentServer::SetViewportRect(Gfx::IntRect({ horizontal_scrollbar().value(), vertical_scrollbar().value() }, available_size()))); - if (m_front_bitmap) { - m_front_bitmap = nullptr; - client().post_message(Messages::WebContentServer::RemoveBackingStore(m_front_bitmap_id)); + if (m_client_state.front_bitmap) { + m_client_state.front_bitmap = nullptr; + client().post_message(Messages::WebContentServer::RemoveBackingStore(m_client_state.front_bitmap_id)); } - if (m_back_bitmap) { - m_back_bitmap = nullptr; - client().post_message(Messages::WebContentServer::RemoveBackingStore(m_back_bitmap_id)); + if (m_client_state.back_bitmap) { + m_client_state.back_bitmap = nullptr; + client().post_message(Messages::WebContentServer::RemoveBackingStore(m_client_state.back_bitmap_id)); } - m_front_bitmap_id = -1; - m_back_bitmap_id = -1; - m_has_usable_bitmap = false; + m_client_state.front_bitmap_id = -1; + m_client_state.back_bitmap_id = -1; + m_client_state.has_usable_bitmap = false; if (available_size().is_empty()) return; if (auto new_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::RGB32, available_size())) { - m_front_bitmap = move(new_bitmap); - m_front_bitmap_id = m_next_bitmap_id++; - client().post_message(Messages::WebContentServer::AddBackingStore(m_front_bitmap_id, m_front_bitmap->to_shareable_bitmap())); + m_client_state.front_bitmap = move(new_bitmap); + m_client_state.front_bitmap_id = m_client_state.next_bitmap_id++; + client().post_message(Messages::WebContentServer::AddBackingStore(m_client_state.front_bitmap_id, m_client_state.front_bitmap->to_shareable_bitmap())); } if (auto new_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::RGB32, available_size())) { - m_back_bitmap = move(new_bitmap); - m_back_bitmap_id = m_next_bitmap_id++; - client().post_message(Messages::WebContentServer::AddBackingStore(m_back_bitmap_id, m_back_bitmap->to_shareable_bitmap())); + m_client_state.back_bitmap = move(new_bitmap); + m_client_state.back_bitmap_id = m_client_state.next_bitmap_id++; + client().post_message(Messages::WebContentServer::AddBackingStore(m_client_state.back_bitmap_id, m_client_state.back_bitmap->to_shareable_bitmap())); } request_repaint(); @@ -157,10 +187,10 @@ void OutOfProcessWebView::theme_change_event(GUI::ThemeChangeEvent& event) void OutOfProcessWebView::notify_server_did_paint(Badge, i32 bitmap_id) { - if (m_back_bitmap_id == bitmap_id) { - m_has_usable_bitmap = true; - swap(m_back_bitmap, m_front_bitmap); - swap(m_back_bitmap_id, m_front_bitmap_id); + if (m_client_state.back_bitmap_id == bitmap_id) { + m_client_state.has_usable_bitmap = true; + swap(m_client_state.back_bitmap, m_client_state.front_bitmap); + swap(m_client_state.back_bitmap_id, m_client_state.front_bitmap_id); update(); } } @@ -256,14 +286,15 @@ void OutOfProcessWebView::request_repaint() { // If this widget was instantiated but not yet added to a window, // it won't have a back bitmap yet, so we can just skip repaint requests. - if (!m_back_bitmap) + if (!m_client_state.back_bitmap) return; - client().post_message(Messages::WebContentServer::Paint(m_back_bitmap->rect().translated(horizontal_scrollbar().value(), vertical_scrollbar().value()), m_back_bitmap_id)); + client().post_message(Messages::WebContentServer::Paint(m_client_state.back_bitmap->rect().translated(horizontal_scrollbar().value(), vertical_scrollbar().value()), m_client_state.back_bitmap_id)); } WebContentClient& OutOfProcessWebView::client() { - return *m_client; + ASSERT(m_client_state.client); + return *m_client_state.client; } } diff --git a/Userland/Libraries/LibWeb/OutOfProcessWebView.h b/Userland/Libraries/LibWeb/OutOfProcessWebView.h index 3a9167a06c..750da66d09 100644 --- a/Userland/Libraries/LibWeb/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWeb/OutOfProcessWebView.h @@ -81,18 +81,22 @@ private: virtual void did_scroll() override; void request_repaint(); + void handle_resize(); + void create_client(); WebContentClient& client(); URL m_url; - RefPtr m_client; - RefPtr m_front_bitmap; - RefPtr m_back_bitmap; - i32 m_front_bitmap_id { -1 }; - i32 m_back_bitmap_id { -1 }; - i32 m_next_bitmap_id { 0 }; - bool m_has_usable_bitmap { false }; + struct ClientState { + RefPtr client; + RefPtr front_bitmap; + RefPtr back_bitmap; + i32 front_bitmap_id { -1 }; + i32 back_bitmap_id { -1 }; + i32 next_bitmap_id { 0 }; + bool has_usable_bitmap { false }; + } m_client_state; }; } diff --git a/Userland/Libraries/LibWeb/WebContentClient.cpp b/Userland/Libraries/LibWeb/WebContentClient.cpp index dd40e426be..087f9f9c9e 100644 --- a/Userland/Libraries/LibWeb/WebContentClient.cpp +++ b/Userland/Libraries/LibWeb/WebContentClient.cpp @@ -37,6 +37,12 @@ WebContentClient::WebContentClient(OutOfProcessWebView& view) handshake(); } +void WebContentClient::die() +{ + ASSERT(on_web_content_process_crash); + on_web_content_process_crash(); +} + void WebContentClient::handshake() { auto response = send_sync(getpid()); diff --git a/Userland/Libraries/LibWeb/WebContentClient.h b/Userland/Libraries/LibWeb/WebContentClient.h index 2078882578..194901a809 100644 --- a/Userland/Libraries/LibWeb/WebContentClient.h +++ b/Userland/Libraries/LibWeb/WebContentClient.h @@ -35,7 +35,7 @@ namespace Web { class OutOfProcessWebView; -class WebContentClient +class WebContentClient final : public IPC::ServerConnection , public WebContentClientEndpoint { C_OBJECT(WebContentClient); @@ -43,9 +43,13 @@ class WebContentClient public: virtual void handshake() override; + Function on_web_content_process_crash; + private: WebContentClient(OutOfProcessWebView&); + virtual void die() override; + virtual void handle(const Messages::WebContentClient::DidPaint&) override; virtual void handle(const Messages::WebContentClient::DidFinishLoading&) override; virtual void handle(const Messages::WebContentClient::DidInvalidateContentRect&) override;