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:
parent
4b8729aea6
commit
364f44d7d8
11 changed files with 118 additions and 32 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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) =|
|
||||
|
|
|
@ -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) =|
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue