1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 16:57:46 +00:00

LibWebView+WebContent: Wait for dialog responses without blocking IPC

Currently, the WebContent process is completely blocked while waiting
for a response to a dialog request. This patch allows the IPC event loop
to continue executing while only blocking the HTML event loop.

This will allow other processes like WebDriver to continue to operate on
the WebContent process while a dialog is open.
This commit is contained in:
Timothy Flynn 2022-11-15 15:49:36 -05:00 committed by Linus Groh
parent 4b8729aea6
commit 364f44d7d8
11 changed files with 118 additions and 32 deletions

View file

@ -576,4 +576,19 @@ void ConnectionFromClient::set_system_visibility_state(bool visible)
: Web::HTML::VisibilityState::Hidden);
}
void ConnectionFromClient::alert_closed()
{
m_page_host->alert_closed();
}
void ConnectionFromClient::confirm_closed(bool accepted)
{
m_page_host->confirm_closed(accepted);
}
void ConnectionFromClient::prompt_closed(String const& response)
{
m_page_host->prompt_closed(response);
}
}

View file

@ -84,6 +84,10 @@ private:
virtual void run_javascript(String const&) override;
virtual void js_console_request_messages(i32) override;
virtual void alert_closed() override;
virtual void confirm_closed(bool accepted) override;
virtual void prompt_closed(String const& response) override;
virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override;
virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override;

View file

@ -7,13 +7,17 @@
#include "PageHost.h"
#include "ConnectionFromClient.h"
#include <AK/SourceLocation.h>
#include <LibGfx/Painter.h>
#include <LibGfx/ShareableBitmap.h>
#include <LibGfx/SystemTheme.h>
#include <LibWeb/Cookie/ParsedCookie.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/EventLoop/EventLoop.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/Layout/InitialContainingBlock.h>
#include <LibWeb/Painting/PaintableBox.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
#include <LibWeb/Platform/Timer.h>
#include <WebContent/WebContentClientEndpoint.h>
#include <WebContent/WebDriverConnection.h>
@ -233,33 +237,72 @@ void PageHost::page_did_request_link_context_menu(Gfx::IntPoint const& content_p
m_client.async_did_request_link_context_menu(content_position, url, target, modifiers);
}
template<typename ResponseType>
static ResponseType spin_event_loop_until_dialog_closed(ConnectionFromClient& client, Optional<ResponseType>& response, SourceLocation location = SourceLocation::current())
{
auto& event_loop = Web::HTML::current_settings_object().responsible_event_loop();
ScopeGuard guard { [&] { event_loop.set_execution_paused(false); } };
event_loop.set_execution_paused(true);
Web::Platform::EventLoopPlugin::the().spin_until([&]() {
return response.has_value() || !client.is_open();
});
if (!client.is_open()) {
dbgln("WebContent client disconnected during {}. Exiting peacefully.", location.function_name());
exit(0);
}
return response.release_value();
}
void PageHost::page_did_request_alert(String const& message)
{
auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestAlert>(message);
if (!response) {
dbgln("WebContent client disconnected during DidRequestAlert. Exiting peacefully.");
exit(0);
m_pending_dialog = PendingDialog::Alert;
m_client.async_did_request_alert(message);
spin_event_loop_until_dialog_closed(m_client, m_pending_alert_response);
}
void PageHost::alert_closed()
{
if (m_pending_dialog == PendingDialog::Alert) {
m_pending_dialog = PendingDialog::None;
m_pending_alert_response = Empty {};
}
}
bool PageHost::page_did_request_confirm(String const& message)
{
auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestConfirm>(message);
if (!response) {
dbgln("WebContent client disconnected during DidRequestConfirm. Exiting peacefully.");
exit(0);
m_pending_dialog = PendingDialog::Confirm;
m_client.async_did_request_confirm(message);
return spin_event_loop_until_dialog_closed(m_client, m_pending_confirm_response);
}
void PageHost::confirm_closed(bool accepted)
{
if (m_pending_dialog == PendingDialog::Confirm) {
m_pending_dialog = PendingDialog::None;
m_pending_confirm_response = accepted;
}
return response->take_result();
}
String PageHost::page_did_request_prompt(String const& message, String const& default_)
{
auto response = m_client.send_sync_but_allow_failure<Messages::WebContentClient::DidRequestPrompt>(message, default_);
if (!response) {
dbgln("WebContent client disconnected during DidRequestPrompt. Exiting peacefully.");
exit(0);
m_pending_dialog = PendingDialog::Prompt;
m_client.async_did_request_prompt(message, default_);
return spin_event_loop_until_dialog_closed(m_client, m_pending_prompt_response);
}
void PageHost::prompt_closed(String response)
{
if (m_pending_dialog == PendingDialog::Prompt) {
m_pending_dialog = PendingDialog::None;
m_pending_prompt_response = move(response);
}
return response->take_response();
}
void PageHost::page_did_change_favicon(Gfx::Bitmap const& favicon)

View file

@ -43,6 +43,19 @@ public:
ErrorOr<void> connect_to_webdriver(String const& webdriver_ipc_path);
void alert_closed();
void confirm_closed(bool accepted);
void prompt_closed(String response);
enum class PendingDialog {
None,
Alert,
Confirm,
Prompt,
};
bool has_pending_dialog() const { return m_pending_dialog != PendingDialog::None; }
PendingDialog pending_dialog() const { return m_pending_dialog; }
private:
// ^PageClient
virtual Gfx::Palette palette() const override;
@ -95,6 +108,11 @@ private:
Web::CSS::PreferredColorScheme m_preferred_color_scheme { Web::CSS::PreferredColorScheme::Auto };
RefPtr<WebDriverConnection> m_webdriver;
PendingDialog m_pending_dialog { PendingDialog::None };
Optional<Empty> m_pending_alert_response;
Optional<bool> m_pending_confirm_response;
Optional<String> m_pending_prompt_response;
};
}

View file

@ -29,9 +29,9 @@ endpoint WebContentClient
did_request_context_menu(Gfx::IntPoint content_position) =|
did_request_link_context_menu(Gfx::IntPoint content_position, URL url, String target, unsigned modifiers) =|
did_request_image_context_menu(Gfx::IntPoint content_position, URL url, String target, unsigned modifiers, Gfx::ShareableBitmap bitmap) =|
did_request_alert(String message) => ()
did_request_confirm(String message) => (bool result)
did_request_prompt(String message, String default_) => (String response)
did_request_alert(String message) =|
did_request_confirm(String message) =|
did_request_prompt(String message, String default_) =|
did_get_source(URL url, String source) =|
did_get_dom_tree(String dom_tree) =|
did_get_dom_node_properties(i32 node_id, String specified_style, String computed_style, String custom_properties, String node_box_sizing_json) =|

View file

@ -65,4 +65,8 @@ endpoint WebContentServer
handle_file_return(i32 error, Optional<IPC::File> file, i32 request_id) =|
set_system_visibility_state(bool visible) =|
alert_closed() =|
confirm_closed(bool accepted) =|
prompt_closed(String response) =|
}