LibWeb+WebContent+WebDriver+UI: Make window rect updates asynchronous

It's currently possible for window size/position updates to hang, as the
underlying IPCs are synchronous. This updates the WebDriver endpoint to
be async, to unblock the WebContent process while the update is ongoing.
The UI process is now responsible for informing WebContent when the
update is complete.
This commit is contained in:
Timothy Flynn 2024-10-28 23:37:11 -04:00 committed by Tim Ledbetter
commit fa83cc722c
Notes: github-actions[bot] 2024-10-29 11:04:46 +00:00
22 changed files with 94 additions and 43 deletions

View file

@ -1007,26 +1007,26 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
m_web_view_bridge->on_reposition_window = [weak_self](auto position) { m_web_view_bridge->on_reposition_window = [weak_self](auto position) {
LadybirdWebView* self = weak_self; LadybirdWebView* self = weak_self;
if (self == nil) { if (self == nil) {
return Gfx::IntPoint {}; return;
} }
position = Ladybird::compute_origin_relative_to_window([self window], position); position = Ladybird::compute_origin_relative_to_window([self window], position);
[[self window] setFrameOrigin:Ladybird::gfx_point_to_ns_point(position)]; [[self window] setFrameOrigin:Ladybird::gfx_point_to_ns_point(position)];
position = Ladybird::ns_point_to_gfx_point([[self window] frame].origin); m_web_view_bridge->did_update_window_rect();
return Ladybird::compute_origin_relative_to_window([self window], position);
}; };
m_web_view_bridge->on_resize_window = [weak_self](auto size) { m_web_view_bridge->on_resize_window = [weak_self](auto size) {
LadybirdWebView* self = weak_self; LadybirdWebView* self = weak_self;
if (self == nil) { if (self == nil) {
return Gfx::IntSize {}; return;
} }
auto frame = [[self window] frame]; auto frame = [[self window] frame];
frame.size = Ladybird::gfx_size_to_ns_size(size); frame.size = Ladybird::gfx_size_to_ns_size(size);
[[self window] setFrame:frame display:YES]; [[self window] setFrame:frame display:YES];
return Ladybird::ns_size_to_gfx_size([[self window] frame].size); m_web_view_bridge->did_update_window_rect();
}; };
m_web_view_bridge->on_maximize_window = [weak_self]() { m_web_view_bridge->on_maximize_window = [weak_self]() {

View file

@ -354,12 +354,12 @@ Tab::Tab(BrowserWindow* window, RefPtr<WebView::WebContentClient> parent_client,
view().on_reposition_window = [this](auto const& position) { view().on_reposition_window = [this](auto const& position) {
m_window->move(position.x(), position.y()); m_window->move(position.x(), position.y());
return Gfx::IntPoint { m_window->x(), m_window->y() }; view().did_update_window_rect();
}; };
view().on_resize_window = [this](auto const& size) { view().on_resize_window = [this](auto const& size) {
m_window->resize(size.width(), size.height()); m_window->resize(size.width(), size.height());
return Gfx::IntSize { m_window->width(), m_window->height() }; view().did_update_window_rect();
}; };
view().on_maximize_window = [this]() { view().on_maximize_window = [this]() {

View file

@ -48,6 +48,7 @@ void Page::visit_edges(JS::Cell::Visitor& visitor)
Base::visit_edges(visitor); Base::visit_edges(visitor);
visitor.visit(m_top_level_traversable); visitor.visit(m_top_level_traversable);
visitor.visit(m_client); visitor.visit(m_client);
visitor.visit(m_window_rect_observer);
visitor.visit(m_on_pending_dialog_closed); visitor.visit(m_on_pending_dialog_closed);
} }
@ -254,6 +255,12 @@ JS::NonnullGCPtr<HTML::TraversableNavigable> Page::top_level_traversable() const
return *m_top_level_traversable; return *m_top_level_traversable;
} }
void Page::did_update_window_rect()
{
if (m_window_rect_observer)
m_window_rect_observer->function()({ window_position(), window_size() });
}
template<typename ResponseType> template<typename ResponseType>
static ResponseType spin_event_loop_until_dialog_closed(PageClient& client, Optional<ResponseType>& response, SourceLocation location = SourceLocation::current()) static ResponseType spin_event_loop_until_dialog_closed(PageClient& client, Optional<ResponseType>& response, SourceLocation location = SourceLocation::current())
{ {

View file

@ -127,6 +127,9 @@ public:
DevicePixelSize window_size() const { return m_window_size; } DevicePixelSize window_size() const { return m_window_size; }
void set_window_size(DevicePixelSize size) { m_window_size = size; } void set_window_size(DevicePixelSize size) { m_window_size = size; }
void did_update_window_rect();
void set_window_rect_observer(JS::GCPtr<JS::HeapFunction<void(DevicePixelRect)>> window_rect_observer) { m_window_rect_observer = window_rect_observer; }
void did_request_alert(String const& message); void did_request_alert(String const& message);
void alert_closed(); void alert_closed();
@ -245,6 +248,7 @@ private:
DevicePixelPoint m_window_position {}; DevicePixelPoint m_window_position {};
DevicePixelSize m_window_size {}; DevicePixelSize m_window_size {};
JS::GCPtr<JS::HeapFunction<void(DevicePixelRect)>> m_window_rect_observer;
PendingDialog m_pending_dialog { PendingDialog::None }; PendingDialog m_pending_dialog { PendingDialog::None };
Optional<String> m_pending_dialog_text; Optional<String> m_pending_dialog_text;
@ -310,8 +314,8 @@ public:
virtual void page_did_request_navigate_back() { } virtual void page_did_request_navigate_back() { }
virtual void page_did_request_navigate_forward() { } virtual void page_did_request_navigate_forward() { }
virtual void page_did_request_refresh() { } virtual void page_did_request_refresh() { }
virtual Gfx::IntSize page_did_request_resize_window(Gfx::IntSize) { return {}; } virtual void page_did_request_resize_window(Gfx::IntSize) { }
virtual Gfx::IntPoint page_did_request_reposition_window(Gfx::IntPoint) { return {}; } virtual void page_did_request_reposition_window(Gfx::IntPoint) { }
virtual void page_did_request_restore_window() { } virtual void page_did_request_restore_window() { }
virtual Gfx::IntRect page_did_request_maximize_window() { return {}; } virtual Gfx::IntRect page_did_request_maximize_window() { return {}; }
virtual Gfx::IntRect page_did_request_minimize_window() { return {}; } virtual Gfx::IntRect page_did_request_minimize_window() { return {}; }

View file

@ -87,6 +87,11 @@ void ViewImplementation::set_window_size(Gfx::IntSize size)
client().async_set_window_size(m_client_state.page_index, size.to_type<Web::DevicePixels>()); client().async_set_window_size(m_client_state.page_index, size.to_type<Web::DevicePixels>());
} }
void ViewImplementation::did_update_window_rect()
{
client().async_did_update_window_rect(m_client_state.page_index);
}
void ViewImplementation::load(URL::URL const& url) void ViewImplementation::load(URL::URL const& url)
{ {
m_url = url; m_url = url;

View file

@ -52,6 +52,7 @@ public:
void set_window_position(Gfx::IntPoint); void set_window_position(Gfx::IntPoint);
void set_window_size(Gfx::IntSize); void set_window_size(Gfx::IntSize);
void did_update_window_rect();
void load(URL::URL const&); void load(URL::URL const&);
void load_html(StringView); void load_html(StringView);
@ -202,8 +203,8 @@ public:
Function<void(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)> on_received_console_messages; Function<void(i32 start_index, Vector<ByteString> const& message_types, Vector<ByteString> const& messages)> on_received_console_messages;
Function<void(i32 count_waiting)> on_resource_status_change; Function<void(i32 count_waiting)> on_resource_status_change;
Function<void()> on_restore_window; Function<void()> on_restore_window;
Function<Gfx::IntPoint(Gfx::IntPoint)> on_reposition_window; Function<void(Gfx::IntPoint)> on_reposition_window;
Function<Gfx::IntSize(Gfx::IntSize)> on_resize_window; Function<void(Gfx::IntSize)> on_resize_window;
Function<Gfx::IntRect()> on_maximize_window; Function<Gfx::IntRect()> on_maximize_window;
Function<Gfx::IntRect()> on_minimize_window; Function<Gfx::IntRect()> on_minimize_window;
Function<Gfx::IntRect()> on_fullscreen_window; Function<Gfx::IntRect()> on_fullscreen_window;

View file

@ -492,24 +492,20 @@ void WebContentClient::did_request_restore_window(u64 page_id)
} }
} }
Messages::WebContentClient::DidRequestRepositionWindowResponse WebContentClient::did_request_reposition_window(u64 page_id, Gfx::IntPoint position) void WebContentClient::did_request_reposition_window(u64 page_id, Gfx::IntPoint position)
{ {
if (auto view = view_for_page_id(page_id); view.has_value()) { if (auto view = view_for_page_id(page_id); view.has_value()) {
if (view->on_reposition_window) if (view->on_reposition_window)
return view->on_reposition_window(position); view->on_reposition_window(position);
} }
return Gfx::IntPoint {};
} }
Messages::WebContentClient::DidRequestResizeWindowResponse WebContentClient::did_request_resize_window(u64 page_id, Gfx::IntSize size) void WebContentClient::did_request_resize_window(u64 page_id, Gfx::IntSize size)
{ {
if (auto view = view_for_page_id(page_id); view.has_value()) { if (auto view = view_for_page_id(page_id); view.has_value()) {
if (view->on_resize_window) if (view->on_resize_window)
return view->on_resize_window(size); view->on_resize_window(size);
} }
return Gfx::IntSize {};
} }
Messages::WebContentClient::DidRequestMaximizeWindowResponse WebContentClient::did_request_maximize_window(u64 page_id) Messages::WebContentClient::DidRequestMaximizeWindowResponse WebContentClient::did_request_maximize_window(u64 page_id)

View file

@ -100,8 +100,8 @@ private:
virtual void did_close_browsing_context(u64 page_id) override; virtual void did_close_browsing_context(u64 page_id) override;
virtual void did_update_resource_count(u64 page_id, i32 count_waiting) override; virtual void did_update_resource_count(u64 page_id, i32 count_waiting) override;
virtual void did_request_restore_window(u64 page_id) override; virtual void did_request_restore_window(u64 page_id) override;
virtual Messages::WebContentClient::DidRequestRepositionWindowResponse did_request_reposition_window(u64 page_id, Gfx::IntPoint) override; virtual void did_request_reposition_window(u64 page_id, Gfx::IntPoint) override;
virtual Messages::WebContentClient::DidRequestResizeWindowResponse did_request_resize_window(u64 page_id, Gfx::IntSize) override; virtual void did_request_resize_window(u64 page_id, Gfx::IntSize) override;
virtual Messages::WebContentClient::DidRequestMaximizeWindowResponse did_request_maximize_window(u64 page_id) override; virtual Messages::WebContentClient::DidRequestMaximizeWindowResponse did_request_maximize_window(u64 page_id) override;
virtual Messages::WebContentClient::DidRequestMinimizeWindowResponse did_request_minimize_window(u64 page_id) override; virtual Messages::WebContentClient::DidRequestMinimizeWindowResponse did_request_minimize_window(u64 page_id) override;
virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override; virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override;

View file

@ -1082,6 +1082,12 @@ void ConnectionFromClient::set_window_size(u64 page_id, Web::DevicePixelSize siz
page->set_window_size(size); page->set_window_size(size);
} }
void ConnectionFromClient::did_update_window_rect(u64 page_id)
{
if (auto page = this->page(page_id); page.has_value())
page->page().did_update_window_rect();
}
Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient::get_local_storage_entries(u64 page_id) Messages::WebContentServer::GetLocalStorageEntriesResponse ConnectionFromClient::get_local_storage_entries(u64 page_id)
{ {
auto page = this->page(page_id); auto page = this->page(page_id);

View file

@ -103,6 +103,7 @@ private:
virtual void set_device_pixels_per_css_pixel(u64 page_id, float) override; virtual void set_device_pixels_per_css_pixel(u64 page_id, float) override;
virtual void set_window_position(u64 page_id, Web::DevicePixelPoint) override; virtual void set_window_position(u64 page_id, Web::DevicePixelPoint) override;
virtual void set_window_size(u64 page_id, Web::DevicePixelSize) override; virtual void set_window_size(u64 page_id, Web::DevicePixelSize) override;
virtual void did_update_window_rect(u64 page_id) override;
virtual void handle_file_return(u64 page_id, i32 error, Optional<IPC::File> const& file, i32 request_id) override; virtual void handle_file_return(u64 page_id, i32 error, Optional<IPC::File> const& file, i32 request_id) override;
virtual void set_system_visibility_state(u64 page_id, bool visible) override; virtual void set_system_visibility_state(u64 page_id, bool visible) override;

View file

@ -261,14 +261,14 @@ void PageClient::page_did_request_refresh()
client().async_did_request_refresh(m_id); client().async_did_request_refresh(m_id);
} }
Gfx::IntSize PageClient::page_did_request_resize_window(Gfx::IntSize size) void PageClient::page_did_request_resize_window(Gfx::IntSize size)
{ {
return client().did_request_resize_window(m_id, size); client().async_did_request_resize_window(m_id, size);
} }
Gfx::IntPoint PageClient::page_did_request_reposition_window(Gfx::IntPoint position) void PageClient::page_did_request_reposition_window(Gfx::IntPoint position)
{ {
return client().did_request_reposition_window(m_id, position); client().async_did_request_reposition_window(m_id, position);
} }
void PageClient::page_did_request_restore_window() void PageClient::page_did_request_restore_window()

View file

@ -112,8 +112,8 @@ private:
virtual void page_did_request_navigate_back() override; virtual void page_did_request_navigate_back() override;
virtual void page_did_request_navigate_forward() override; virtual void page_did_request_navigate_forward() override;
virtual void page_did_request_refresh() override; virtual void page_did_request_refresh() override;
virtual Gfx::IntSize page_did_request_resize_window(Gfx::IntSize) override; virtual void page_did_request_resize_window(Gfx::IntSize) override;
virtual Gfx::IntPoint page_did_request_reposition_window(Gfx::IntPoint) override; virtual void page_did_request_reposition_window(Gfx::IntPoint) override;
virtual void page_did_request_restore_window() override; virtual void page_did_request_restore_window() override;
virtual Gfx::IntRect page_did_request_maximize_window() override; virtual Gfx::IntRect page_did_request_maximize_window() override;
virtual Gfx::IntRect page_did_request_minimize_window() override; virtual Gfx::IntRect page_did_request_minimize_window() override;

View file

@ -77,8 +77,8 @@ endpoint WebContentClient
did_request_activate_tab(u64 page_id) =| did_request_activate_tab(u64 page_id) =|
did_close_browsing_context(u64 page_id) =| did_close_browsing_context(u64 page_id) =|
did_request_restore_window(u64 page_id) =| did_request_restore_window(u64 page_id) =|
did_request_reposition_window(u64 page_id, Gfx::IntPoint position) => (Gfx::IntPoint window_position) did_request_reposition_window(u64 page_id, Gfx::IntPoint position) =|
did_request_resize_window(u64 page_id, Gfx::IntSize size) => (Gfx::IntSize window_size) did_request_resize_window(u64 page_id, Gfx::IntSize size) =|
did_request_maximize_window(u64 page_id) => (Gfx::IntRect window_rect) did_request_maximize_window(u64 page_id) => (Gfx::IntRect window_rect)
did_request_minimize_window(u64 page_id) => (Gfx::IntRect window_rect) did_request_minimize_window(u64 page_id) => (Gfx::IntRect window_rect)
did_request_fullscreen_window(u64 page_id) => (Gfx::IntRect window_rect) did_request_fullscreen_window(u64 page_id) => (Gfx::IntRect window_rect)

View file

@ -90,6 +90,7 @@ endpoint WebContentServer
set_window_position(u64 page_id, Web::DevicePixelPoint position) =| set_window_position(u64 page_id, Web::DevicePixelPoint position) =|
set_window_size(u64 page_id, Web::DevicePixelSize size) =| set_window_size(u64 page_id, Web::DevicePixelSize size) =|
did_update_window_rect(u64 page_id) =|
get_local_storage_entries(u64 page_id) => (OrderedHashMap<String, String> entries) get_local_storage_entries(u64 page_id) => (OrderedHashMap<String, String> entries)
get_session_storage_entries(u64 page_id) => (OrderedHashMap<String, String> entries) get_session_storage_entries(u64 page_id) => (OrderedHashMap<String, String> entries)

View file

@ -647,10 +647,11 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window
auto const& properties = payload.as_object(); auto const& properties = payload.as_object();
auto resolve_property = [](auto name, auto const& property, i32 min, i32 max) -> ErrorOr<Optional<i32>, Web::WebDriver::Error> { auto resolve_property = [](auto name, auto const& property, double min, double max) -> ErrorOr<Optional<double>, Web::WebDriver::Error> {
if (property.is_null()) if (property.is_null())
return Optional<i32> {}; return OptionalNone {};
auto value = property.template get_integer<i32>();
auto value = property.get_double_with_precision_loss();
if (!value.has_value()) if (!value.has_value())
return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", name)); return Web::WebDriver::Error::from_code(Web::WebDriver::ErrorCode::InvalidArgument, ByteString::formatted("Property '{}' is not a Number", name));
if (*value < min) if (*value < min)
@ -694,29 +695,28 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window
// 11. Restore the window. // 11. Restore the window.
restore_the_window(); restore_the_window();
Gfx::IntRect window_rect; auto& page = current_top_level_browsing_context()->page();
// 11. If width and height are not null: // 11. If width and height are not null:
if (width.has_value() && height.has_value()) { if (width.has_value() && height.has_value()) {
// a. Set the width, in CSS pixels, of the operating system window containing the current top-level browsing context, including any browser chrome and externally drawn window decorations to a value that is as close as possible to width. // a. Set the width, in CSS pixels, of the operating system window containing the current top-level browsing context, including any browser chrome and externally drawn window decorations to a value that is as close as possible to width.
// b. Set the height, in CSS pixels, of the operating system window containing the current top-level browsing context, including any browser chrome and externally drawn window decorations to a value that is as close as possible to height. // b. Set the height, in CSS pixels, of the operating system window containing the current top-level browsing context, including any browser chrome and externally drawn window decorations to a value that is as close as possible to height.
auto size = current_top_level_browsing_context()->page().client().page_did_request_resize_window({ *width, *height }); page.client().page_did_request_resize_window({ *width, *height });
window_rect.set_size(size); ++m_pending_window_rect_requests;
} else {
window_rect.set_size(current_top_level_browsing_context()->page().window_size().to_type<int>());
} }
// 12. If x and y are not null: // 12. If x and y are not null:
if (x.has_value() && y.has_value()) { if (x.has_value() && y.has_value()) {
// a. Run the implementation-specific steps to set the position of the operating system level window containing the current top-level browsing context to the position given by the x and y coordinates. // a. Run the implementation-specific steps to set the position of the operating system level window containing the current top-level browsing context to the position given by the x and y coordinates.
auto position = current_top_level_browsing_context()->page().client().page_did_request_reposition_window({ *x, *y }); page.client().page_did_request_reposition_window({ *x, *y });
window_rect.set_location(position); ++m_pending_window_rect_requests;
} else {
window_rect.set_location(current_top_level_browsing_context()->page().window_position().to_type<int>());
} }
if (m_pending_window_rect_requests == 0)
async_window_rect_updated(serialize_rect(compute_window_rect(page)));
// 14. Return success with data set to the WindowRect object for the current top-level browsing context. // 14. Return success with data set to the WindowRect object for the current top-level browsing context.
return serialize_rect(window_rect); return JsonValue {};
} }
// 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window // 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window
@ -2340,9 +2340,19 @@ void WebDriverConnection::set_current_top_level_browsing_context(Web::HTML::Brow
// 1. Assert: context is a top-level browsing context. // 1. Assert: context is a top-level browsing context.
VERIFY(browsing_context.is_top_level()); VERIFY(browsing_context.is_top_level());
if (m_current_top_level_browsing_context)
m_current_top_level_browsing_context->page().set_window_rect_observer({});
// 2. Set session's current top-level browsing context to context. // 2. Set session's current top-level browsing context to context.
m_current_top_level_browsing_context = browsing_context; m_current_top_level_browsing_context = browsing_context;
if (m_current_top_level_browsing_context) {
m_current_top_level_browsing_context->page().set_window_rect_observer(JS::create_heap_function(m_current_top_level_browsing_context->heap(), [this](Web::DevicePixelRect rect) {
if (m_pending_window_rect_requests > 0 && --m_pending_window_rect_requests == 0)
async_window_rect_updated(serialize_rect(rect.to_type<int>()));
}));
}
// 3. Set the current browsing context with session and context. // 3. Set the current browsing context with session and context.
set_current_browsing_context(browsing_context); set_current_browsing_context(browsing_context);
} }

View file

@ -161,6 +161,8 @@ private:
// https://w3c.github.io/webdriver/#dfn-current-top-level-browsing-context // https://w3c.github.io/webdriver/#dfn-current-top-level-browsing-context
JS::GCPtr<Web::HTML::BrowsingContext> m_current_top_level_browsing_context; JS::GCPtr<Web::HTML::BrowsingContext> m_current_top_level_browsing_context;
size_t m_pending_window_rect_requests { 0 };
JS::GCPtr<JS::Cell> m_action_executor; JS::GCPtr<JS::Cell> m_action_executor;
JS::GCPtr<Web::DOM::DocumentObserver> m_document_observer; JS::GCPtr<Web::DOM::DocumentObserver> m_document_observer;

View file

@ -2,6 +2,7 @@
endpoint WebDriverServer { endpoint WebDriverServer {
navigation_complete(Web::WebDriver::Response response) =| navigation_complete(Web::WebDriver::Response response) =|
window_rect_updated(Web::WebDriver::Response response) =|
script_executed(Web::WebDriver::Response response) =| script_executed(Web::WebDriver::Response response) =|
actions_performed(Web::WebDriver::Response response) =| actions_performed(Web::WebDriver::Response response) =|
dialog_closed(Web::WebDriver::Response response) =| dialog_closed(Web::WebDriver::Response response) =|

View file

@ -397,7 +397,7 @@ Web::WebDriver::Response Client::set_window_rect(Web::WebDriver::Parameters para
{ {
dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/rect"); dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session/<session_id>/window/rect");
auto session = TRY(find_session_with_id(parameters[0])); auto session = TRY(find_session_with_id(parameters[0]));
return session->web_content_connection().set_window_rect(payload); return session->set_window_rect(payload);
} }
// 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window // 11.8.3 Maximize Window, https://w3c.github.io/webdriver/#dfn-maximize-window

View file

@ -209,6 +209,13 @@ Web::WebDriver::Response Session::navigate_to(JsonValue payload) const
}); });
} }
Web::WebDriver::Response Session::set_window_rect(JsonValue payload) const
{
return perform_async_action(web_content_connection().on_window_rect_updated, [&]() {
return web_content_connection().set_window_rect(move(payload));
});
}
Web::WebDriver::Response Session::execute_script(JsonValue payload, ScriptMode mode) const Web::WebDriver::Response Session::execute_script(JsonValue payload, ScriptMode mode) const
{ {
return perform_async_action(web_content_connection().on_script_executed, [&]() { return perform_async_action(web_content_connection().on_script_executed, [&]() {

View file

@ -65,6 +65,8 @@ public:
}; };
Web::WebDriver::Response execute_script(JsonValue, ScriptMode) const; Web::WebDriver::Response execute_script(JsonValue, ScriptMode) const;
Web::WebDriver::Response set_window_rect(JsonValue) const;
Web::WebDriver::Response element_click(String) const; Web::WebDriver::Response element_click(String) const;
Web::WebDriver::Response element_send_keys(String, JsonValue) const; Web::WebDriver::Response element_send_keys(String, JsonValue) const;
Web::WebDriver::Response perform_actions(JsonValue) const; Web::WebDriver::Response perform_actions(JsonValue) const;

View file

@ -26,6 +26,12 @@ void WebContentConnection::navigation_complete(Web::WebDriver::Response const& r
on_navigation_complete(response); on_navigation_complete(response);
} }
void WebContentConnection::window_rect_updated(Web::WebDriver::Response const& response)
{
if (on_window_rect_updated)
on_window_rect_updated(response);
}
void WebContentConnection::script_executed(Web::WebDriver::Response const& response) void WebContentConnection::script_executed(Web::WebDriver::Response const& response)
{ {
if (on_script_executed) if (on_script_executed)

View file

@ -23,6 +23,7 @@ public:
Function<void()> on_close; Function<void()> on_close;
Function<void(Web::WebDriver::Response)> on_navigation_complete; Function<void(Web::WebDriver::Response)> on_navigation_complete;
Function<void(Web::WebDriver::Response)> on_window_rect_updated;
Function<void(Web::WebDriver::Response)> on_script_executed; Function<void(Web::WebDriver::Response)> on_script_executed;
Function<void(Web::WebDriver::Response)> on_actions_performed; Function<void(Web::WebDriver::Response)> on_actions_performed;
Function<void(Web::WebDriver::Response)> on_dialog_closed; Function<void(Web::WebDriver::Response)> on_dialog_closed;
@ -31,6 +32,7 @@ private:
virtual void die() override; virtual void die() override;
virtual void navigation_complete(Web::WebDriver::Response const&) override; virtual void navigation_complete(Web::WebDriver::Response const&) override;
virtual void window_rect_updated(Web::WebDriver::Response const&) override;
virtual void script_executed(Web::WebDriver::Response const&) override; virtual void script_executed(Web::WebDriver::Response const&) override;
virtual void actions_performed(Web::WebDriver::Response const&) override; virtual void actions_performed(Web::WebDriver::Response const&) override;
virtual void dialog_closed(Web::WebDriver::Response const&) override; virtual void dialog_closed(Web::WebDriver::Response const&) override;