From 3ca2ee9c722dab096ea98fde0f173ecf18562cb4 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 28 Oct 2024 23:45:18 -0400 Subject: [PATCH] LibWeb+WebContent+WebDriver+UI: Make window min/maximize asynchronous This follows suit of previous changes to never block the WebContent process in WebDriver endpoints. --- Ladybird/AppKit/UI/LadybirdWebView.mm | 17 +- Ladybird/Qt/Tab.cpp | 5 +- Userland/Libraries/LibWeb/Page/Page.h | 6 +- .../Libraries/LibWebView/ViewImplementation.h | 6 +- .../Libraries/LibWebView/WebContentClient.cpp | 18 +- .../Libraries/LibWebView/WebContentClient.h | 6 +- Userland/Services/WebContent/PageClient.cpp | 12 +- Userland/Services/WebContent/PageClient.h | 6 +- .../Services/WebContent/WebContentClient.ipc | 6 +- .../WebContent/WebDriverConnection.cpp | 156 ++++++++++-------- .../Services/WebContent/WebDriverConnection.h | 9 +- Userland/Services/WebDriver/Client.cpp | 6 +- Userland/Services/WebDriver/Session.cpp | 22 ++- Userland/Services/WebDriver/Session.h | 3 + 14 files changed, 156 insertions(+), 122 deletions(-) diff --git a/Ladybird/AppKit/UI/LadybirdWebView.mm b/Ladybird/AppKit/UI/LadybirdWebView.mm index 4ebda1e5d01..0d04e761d34 100644 --- a/Ladybird/AppKit/UI/LadybirdWebView.mm +++ b/Ladybird/AppKit/UI/LadybirdWebView.mm @@ -1032,34 +1032,35 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_ m_web_view_bridge->on_maximize_window = [weak_self]() { LadybirdWebView* self = weak_self; if (self == nil) { - return Gfx::IntRect {}; + return; } - auto frame = [[NSScreen mainScreen] frame]; + + auto frame = [[[self window] screen] frame]; [[self window] setFrame:frame display:YES]; - return Ladybird::ns_rect_to_gfx_rect([[self window] frame]); + m_web_view_bridge->did_update_window_rect(); }; m_web_view_bridge->on_minimize_window = [weak_self]() { LadybirdWebView* self = weak_self; if (self == nil) { - return Gfx::IntRect {}; + return; } - [[self window] setIsMiniaturized:YES]; - return Ladybird::ns_rect_to_gfx_rect([[self window] frame]); + [[self window] setIsMiniaturized:YES]; }; m_web_view_bridge->on_fullscreen_window = [weak_self]() { LadybirdWebView* self = weak_self; if (self == nil) { - return Gfx::IntRect {}; + return; } + if (([[self window] styleMask] & NSWindowStyleMaskFullScreen) == 0) { [[self window] toggleFullScreen:nil]; } - return Ladybird::ns_rect_to_gfx_rect([[self window] frame]); + m_web_view_bridge->did_update_window_rect(); }; m_web_view_bridge->on_received_source = [weak_self](auto const& url, auto const& base_url, auto const& source) { diff --git a/Ladybird/Qt/Tab.cpp b/Ladybird/Qt/Tab.cpp index 44449ecd148..176bf426fa4 100644 --- a/Ladybird/Qt/Tab.cpp +++ b/Ladybird/Qt/Tab.cpp @@ -364,17 +364,16 @@ Tab::Tab(BrowserWindow* window, RefPtr parent_client, view().on_maximize_window = [this]() { m_window->showMaximized(); - return Gfx::IntRect { m_window->x(), m_window->y(), m_window->width(), m_window->height() }; + view().did_update_window_rect(); }; view().on_minimize_window = [this]() { m_window->showMinimized(); - return Gfx::IntRect { m_window->x(), m_window->y(), m_window->width(), m_window->height() }; }; view().on_fullscreen_window = [this]() { m_window->showFullScreen(); - return Gfx::IntRect { m_window->x(), m_window->y(), m_window->width(), m_window->height() }; + view().did_update_window_rect(); }; view().on_insert_clipboard_entry = [](auto const& data, auto const&, auto const& mime_type) { diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index 3b7a83b8e64..c41d0bfec61 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -317,9 +317,9 @@ public: virtual void page_did_request_resize_window(Gfx::IntSize) { } virtual void page_did_request_reposition_window(Gfx::IntPoint) { } virtual void page_did_request_restore_window() { } - virtual Gfx::IntRect page_did_request_maximize_window() { return {}; } - virtual Gfx::IntRect page_did_request_minimize_window() { return {}; } - virtual Gfx::IntRect page_did_request_fullscreen_window() { return {}; } + virtual void page_did_request_maximize_window() { } + virtual void page_did_request_minimize_window() { } + virtual void page_did_request_fullscreen_window() { } virtual void page_did_start_loading(URL::URL const&, bool is_redirect) { (void)is_redirect; } virtual void page_did_create_new_document(Web::DOM::Document&) { } virtual void page_did_change_active_document_in_top_level_browsing_context(Web::DOM::Document&) { } diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index 597bd36be3a..364b7636c02 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -205,9 +205,9 @@ public: Function on_restore_window; Function on_reposition_window; Function on_resize_window; - Function on_maximize_window; - Function on_minimize_window; - Function on_fullscreen_window; + Function on_maximize_window; + Function on_minimize_window; + Function on_fullscreen_window; Function on_request_color_picker; Function on_request_file_picker; Function items)> on_request_select_dropdown; diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp index 55bee592290..1f1e655f688 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.cpp +++ b/Userland/Libraries/LibWebView/WebContentClient.cpp @@ -508,34 +508,28 @@ void WebContentClient::did_request_resize_window(u64 page_id, Gfx::IntSize size) } } -Messages::WebContentClient::DidRequestMaximizeWindowResponse WebContentClient::did_request_maximize_window(u64 page_id) +void WebContentClient::did_request_maximize_window(u64 page_id) { if (auto view = view_for_page_id(page_id); view.has_value()) { if (view->on_maximize_window) - return view->on_maximize_window(); + view->on_maximize_window(); } - - return Gfx::IntRect {}; } -Messages::WebContentClient::DidRequestMinimizeWindowResponse WebContentClient::did_request_minimize_window(u64 page_id) +void WebContentClient::did_request_minimize_window(u64 page_id) { if (auto view = view_for_page_id(page_id); view.has_value()) { if (view->on_minimize_window) - return view->on_minimize_window(); + view->on_minimize_window(); } - - return Gfx::IntRect {}; } -Messages::WebContentClient::DidRequestFullscreenWindowResponse WebContentClient::did_request_fullscreen_window(u64 page_id) +void WebContentClient::did_request_fullscreen_window(u64 page_id) { if (auto view = view_for_page_id(page_id); view.has_value()) { if (view->on_fullscreen_window) - return view->on_fullscreen_window(); + view->on_fullscreen_window(); } - - return Gfx::IntRect {}; } void WebContentClient::did_request_file(u64 page_id, ByteString const& path, i32 request_id) diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h index afd041a0e6c..7d442b6a613 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.h +++ b/Userland/Libraries/LibWebView/WebContentClient.h @@ -102,9 +102,9 @@ private: virtual void did_request_restore_window(u64 page_id) override; virtual void did_request_reposition_window(u64 page_id, Gfx::IntPoint) 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::DidRequestMinimizeWindowResponse did_request_minimize_window(u64 page_id) override; - virtual Messages::WebContentClient::DidRequestFullscreenWindowResponse did_request_fullscreen_window(u64 page_id) override; + virtual void did_request_maximize_window(u64 page_id) override; + virtual void did_request_minimize_window(u64 page_id) override; + virtual void did_request_fullscreen_window(u64 page_id) override; virtual void did_request_file(u64 page_id, ByteString const& path, i32) override; virtual void did_request_color_picker(u64 page_id, Color const& current_color) override; virtual void did_request_file_picker(u64 page_id, Web::HTML::FileFilter const& accepted_file_types, Web::HTML::AllowMultipleFiles) override; diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index 33050caf00d..d22f3b504fd 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -276,19 +276,19 @@ void PageClient::page_did_request_restore_window() client().async_did_request_restore_window(m_id); } -Gfx::IntRect PageClient::page_did_request_maximize_window() +void PageClient::page_did_request_maximize_window() { - return client().did_request_maximize_window(m_id); + client().async_did_request_maximize_window(m_id); } -Gfx::IntRect PageClient::page_did_request_minimize_window() +void PageClient::page_did_request_minimize_window() { - return client().did_request_minimize_window(m_id); + client().async_did_request_minimize_window(m_id); } -Gfx::IntRect PageClient::page_did_request_fullscreen_window() +void PageClient::page_did_request_fullscreen_window() { - return client().did_request_fullscreen_window(m_id); + client().async_did_request_fullscreen_window(m_id); } void PageClient::page_did_request_tooltip_override(Web::CSSPixelPoint position, ByteString const& title) diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index c7a0e690767..fff2970c9be 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -115,9 +115,9 @@ private: virtual void page_did_request_resize_window(Gfx::IntSize) override; virtual void page_did_request_reposition_window(Gfx::IntPoint) override; virtual void page_did_request_restore_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_fullscreen_window() override; + virtual void page_did_request_maximize_window() override; + virtual void page_did_request_minimize_window() override; + virtual void page_did_request_fullscreen_window() override; virtual void page_did_request_tooltip_override(Web::CSSPixelPoint, ByteString const&) override; virtual void page_did_stop_tooltip_override() override; virtual void page_did_enter_tooltip_area(ByteString const&) override; diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index c6dfe526eeb..fdd26722073 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -79,9 +79,9 @@ endpoint WebContentClient did_request_restore_window(u64 page_id) =| did_request_reposition_window(u64 page_id, Gfx::IntPoint position) =| did_request_resize_window(u64 page_id, Gfx::IntSize size) =| - did_request_maximize_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_maximize_window(u64 page_id) =| + did_request_minimize_window(u64 page_id) =| + did_request_fullscreen_window(u64 page_id) =| did_request_file(u64 page_id, ByteString path, i32 request_id) =| did_request_color_picker(u64 page_id, Color current_color) =| did_request_file_picker(u64 page_id, Web::HTML::FileFilter accepted_file_types, Web::HTML::AllowMultipleFiles allow_multiple_files) =| diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index c24cdcd2e6a..1cda8802f8b 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -693,27 +693,27 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window // FIXME: 10. Fully exit fullscreen. // 11. Restore the window. - restore_the_window(); + restore_the_window(JS::create_heap_function(current_top_level_browsing_context()->heap(), [this, x, y, width, height]() { + auto& page = current_top_level_browsing_context()->page(); - auto& page = current_top_level_browsing_context()->page(); + // 11. If width and height are not null: + 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. + // 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. + page.client().page_did_request_resize_window({ *width, *height }); + ++m_pending_window_rect_requests; + } - // 11. If width and height are not null: - 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. - // 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. - page.client().page_did_request_resize_window({ *width, *height }); - ++m_pending_window_rect_requests; - } + // 12. If x and y are not null: + 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. + page.client().page_did_request_reposition_window({ *x, *y }); + ++m_pending_window_rect_requests; + } - // 12. If x and y are not null: - 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. - page.client().page_did_request_reposition_window({ *x, *y }); - ++m_pending_window_rect_requests; - } - - if (m_pending_window_rect_requests == 0) - async_window_rect_updated(serialize_rect(compute_window_rect(page))); + 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. return JsonValue {}; @@ -733,13 +733,13 @@ Messages::WebDriverClient::MaximizeWindowResponse WebDriverConnection::maximize_ // FIXME: 4. Fully exit fullscreen. // 5. Restore the window. - restore_the_window(); - - // 6. Maximize the window of the current top-level browsing context. - auto window_rect = maximize_the_window(); + restore_the_window(JS::create_heap_function(current_top_level_browsing_context()->heap(), [this]() { + // 6. Maximize the window of the current top-level browsing context. + maximize_the_window(); + })); // 7. 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.4 Minimize Window, https://w3c.github.io/webdriver/#minimize-window @@ -756,10 +756,13 @@ Messages::WebDriverClient::MinimizeWindowResponse WebDriverConnection::minimize_ // FIXME: 4. Fully exit fullscreen. // 5. Iconify the window. - auto window_rect = iconify_the_window(); + iconify_the_window(JS::create_heap_function(current_top_level_browsing_context()->heap(), [this]() { + auto& page = current_top_level_browsing_context()->page(); + async_window_rect_updated(serialize_rect(compute_window_rect(page))); + })); // 6. 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.5 Fullscreen Window, https://w3c.github.io/webdriver/#dfn-fullscreen-window @@ -774,15 +777,16 @@ Messages::WebDriverClient::FullscreenWindowResponse WebDriverConnection::fullscr TRY(handle_any_user_prompts()); // 4. Restore the window. - restore_the_window(); - - // 5. FIXME: Call fullscreen an element with the current top-level browsing context’s active document’s document element. - // As described in https://fullscreen.spec.whatwg.org/#fullscreen-an-element - // NOTE: What we do here is basically `requestFullscreen(options)` with options["navigationUI"]="show" - auto rect = current_top_level_browsing_context()->page().client().page_did_request_fullscreen_window(); + restore_the_window(JS::create_heap_function(current_top_level_browsing_context()->heap(), [this]() { + // 5. FIXME: Call fullscreen an element with the current top-level browsing context’s active document’s document element. + // As described in https://fullscreen.spec.whatwg.org/#fullscreen-an-element + // NOTE: What we do here is basically `requestFullscreen(options)` with options["navigationUI"]="show" + current_top_level_browsing_context()->page().client().page_did_request_fullscreen_window(); + ++m_pending_window_rect_requests; + })); // 6. Return success with data set to the WindowRect object for the current top-level browsing context. - return serialize_rect(rect); + return JsonValue {}; } // Extension Consume User Activation, https://html.spec.whatwg.org/multipage/interaction.html#user-activation-user-agent-automation @@ -2521,56 +2525,66 @@ void WebDriverConnection::page_did_open_dialog(Badge) m_navigation_timer->stop_and_fire_timeout_handler(); } -// https://w3c.github.io/webdriver/#dfn-restore-the-window -void WebDriverConnection::restore_the_window() -{ - // To restore the window, given an operating system level window with an associated top-level browsing context, run implementation-specific steps to restore or unhide the window to the visible screen. - current_top_level_browsing_context()->page().client().page_did_request_restore_window(); - - // Do not return from this operation until the visibility state of the top-level browsing context’s active document has reached the visible state, or until the operation times out. - // FIXME: It isn't clear which timeout should be used here. - auto page_load_timeout_fired = false; - auto timer = Core::Timer::create_single_shot(m_timeouts_configuration.page_load_timeout.value_or(300'000), [&] { - page_load_timeout_fired = true; - }); - timer->start(); - - Web::Platform::EventLoopPlugin::the().spin_until([&]() { - auto state = current_top_level_browsing_context()->top_level_traversable()->system_visibility_state(); - return page_load_timeout_fired || state == Web::HTML::VisibilityState::Visible; - }); -} - // https://w3c.github.io/webdriver/#dfn-maximize-the-window -Gfx::IntRect WebDriverConnection::maximize_the_window() +void WebDriverConnection::maximize_the_window() { - // To maximize the window, given an operating system level window with an associated top-level browsing context, run the implementation-specific steps to transition the operating system level window into the maximized window state. - auto rect = current_top_level_browsing_context()->page().client().page_did_request_maximize_window(); - + // To maximize the window, given an operating system level window with an associated top-level browsing context, run + // the implementation-specific steps to transition the operating system level window into the maximized window state. // Return when the window has completed the transition, or within an implementation-defined timeout. - return rect; + current_top_level_browsing_context()->page().client().page_did_request_maximize_window(); + ++m_pending_window_rect_requests; } // https://w3c.github.io/webdriver/#dfn-iconify-the-window -Gfx::IntRect WebDriverConnection::iconify_the_window() +void WebDriverConnection::iconify_the_window(JS::NonnullGCPtr> on_complete) { - // To iconify the window, given an operating system level window with an associated top-level browsing context, run implementation-specific steps to iconify, minimize, or hide the window from the visible screen. - auto rect = current_top_level_browsing_context()->page().client().page_did_request_minimize_window(); + // To iconify the window, given an operating system level window with an associated top-level browsing context, run + // implementation-specific steps to iconify, minimize, or hide the window from the visible screen. + current_top_level_browsing_context()->page().client().page_did_request_minimize_window(); - // Do not return from this operation until the visibility state of the top-level browsing context’s active document has reached the hidden state, or until the operation times out. - // FIXME: It isn't clear which timeout should be used here. - auto page_load_timeout_fired = false; - auto timer = Core::Timer::create_single_shot(m_timeouts_configuration.page_load_timeout.value_or(300'000), [&] { - page_load_timeout_fired = true; - }); - timer->start(); + // Do not return from this operation until the visibility state of the top-level browsing context’s active document + // has reached the hidden state, or until the operation times out. + wait_for_visibility_state(on_complete, Web::HTML::VisibilityState::Hidden); +} - Web::Platform::EventLoopPlugin::the().spin_until([&]() { - auto state = current_top_level_browsing_context()->top_level_traversable()->system_visibility_state(); - return page_load_timeout_fired || state == Web::HTML::VisibilityState::Hidden; +// https://w3c.github.io/webdriver/#dfn-restore-the-window +void WebDriverConnection::restore_the_window(JS::NonnullGCPtr> on_complete) +{ + // To restore the window, given an operating system level window with an associated top-level browsing context, run + // implementation-specific steps to restore or unhide the window to the visible screen. + current_top_level_browsing_context()->page().client().page_did_request_restore_window(); + + // Do not return from this operation until the visibility state of the top-level browsing context’s active document + // has reached the visible state, or until the operation times out. + wait_for_visibility_state(on_complete, Web::HTML::VisibilityState::Visible); +} + +void WebDriverConnection::wait_for_visibility_state(JS::NonnullGCPtr> on_complete, Web::HTML::VisibilityState target_visibility_state) +{ + static constexpr auto VISIBILITY_STATE_TIMEOUT_MS = 5'000; + + auto* document = current_top_level_browsing_context()->active_document(); + auto& realm = document->realm(); + + if (document->visibility_state_value() == target_visibility_state) { + on_complete->function()(); + return; + } + + auto timer = realm.heap().allocate(realm); + m_document_observer = realm.heap().allocate(realm, realm, *document); + + m_document_observer->set_document_visibility_state_observer([timer, target_visibility_state](Web::HTML::VisibilityState visibility_state) { + if (visibility_state == target_visibility_state) + timer->stop_and_fire_timeout_handler(); }); - return rect; + timer->start(VISIBILITY_STATE_TIMEOUT_MS, JS::create_heap_function(realm.heap(), [this, on_complete]() { + m_document_observer->set_document_visibility_state_observer({}); + m_document_observer = nullptr; + + on_complete->function()(); + })); } // https://w3c.github.io/webdriver/#dfn-find diff --git a/Userland/Services/WebContent/WebDriverConnection.h b/Userland/Services/WebContent/WebDriverConnection.h index c2420550e84..e4aad4ced75 100644 --- a/Userland/Services/WebContent/WebDriverConnection.h +++ b/Userland/Services/WebContent/WebDriverConnection.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -120,9 +121,11 @@ private: ErrorOr ensure_current_top_level_browsing_context_is_open(); ErrorOr handle_any_user_prompts(); - void restore_the_window(); - Gfx::IntRect maximize_the_window(); - Gfx::IntRect iconify_the_window(); + + void maximize_the_window(); + void iconify_the_window(JS::NonnullGCPtr>); + void restore_the_window(JS::NonnullGCPtr>); + void wait_for_visibility_state(JS::NonnullGCPtr>, Web::HTML::VisibilityState); using OnNavigationComplete = JS::NonnullGCPtr>; void wait_for_navigation_to_complete(OnNavigationComplete); diff --git a/Userland/Services/WebDriver/Client.cpp b/Userland/Services/WebDriver/Client.cpp index 3447439073e..c050a205e83 100644 --- a/Userland/Services/WebDriver/Client.cpp +++ b/Userland/Services/WebDriver/Client.cpp @@ -406,7 +406,7 @@ Web::WebDriver::Response Client::maximize_window(Web::WebDriver::Parameters para { dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//window/maximize"); auto session = TRY(find_session_with_id(parameters[0])); - return session->web_content_connection().maximize_window(); + return session->maximize_window(); } // 11.8.4 Minimize Window, https://w3c.github.io/webdriver/#minimize-window @@ -415,7 +415,7 @@ Web::WebDriver::Response Client::minimize_window(Web::WebDriver::Parameters para { dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//window/minimize"); auto session = TRY(find_session_with_id(parameters[0])); - return session->web_content_connection().minimize_window(); + return session->minimize_window(); } // 11.8.5 Fullscreen Window, https://w3c.github.io/webdriver/#dfn-fullscreen-window @@ -424,7 +424,7 @@ Web::WebDriver::Response Client::fullscreen_window(Web::WebDriver::Parameters pa { dbgln_if(WEBDRIVER_DEBUG, "Handling POST /session//window/fullscreen"); auto session = TRY(find_session_with_id(parameters[0])); - return session->web_content_connection().fullscreen_window(); + return session->fullscreen_window(); } // Extension: Consume User Activation, https://html.spec.whatwg.org/multipage/interaction.html#user-activation-user-agent-automation diff --git a/Userland/Services/WebDriver/Session.cpp b/Userland/Services/WebDriver/Session.cpp index f40915cac82..9e36d5ca988 100644 --- a/Userland/Services/WebDriver/Session.cpp +++ b/Userland/Services/WebDriver/Session.cpp @@ -216,6 +216,27 @@ Web::WebDriver::Response Session::set_window_rect(JsonValue payload) const }); } +Web::WebDriver::Response Session::maximize_window() const +{ + return perform_async_action(web_content_connection().on_window_rect_updated, [&]() { + return web_content_connection().maximize_window(); + }); +} + +Web::WebDriver::Response Session::minimize_window() const +{ + return perform_async_action(web_content_connection().on_window_rect_updated, [&]() { + return web_content_connection().minimize_window(); + }); +} + +Web::WebDriver::Response Session::fullscreen_window() const +{ + return perform_async_action(web_content_connection().on_window_rect_updated, [&]() { + return web_content_connection().fullscreen_window(); + }); +} + Web::WebDriver::Response Session::execute_script(JsonValue payload, ScriptMode mode) const { return perform_async_action(web_content_connection().on_script_executed, [&]() { @@ -263,5 +284,4 @@ Web::WebDriver::Response Session::accept_alert() const return web_content_connection().accept_alert(); }); } - } diff --git a/Userland/Services/WebDriver/Session.h b/Userland/Services/WebDriver/Session.h index ee745dfe607..17f926ca98d 100644 --- a/Userland/Services/WebDriver/Session.h +++ b/Userland/Services/WebDriver/Session.h @@ -66,6 +66,9 @@ public: Web::WebDriver::Response execute_script(JsonValue, ScriptMode) const; Web::WebDriver::Response set_window_rect(JsonValue) const; + Web::WebDriver::Response maximize_window() const; + Web::WebDriver::Response minimize_window() const; + Web::WebDriver::Response fullscreen_window() const; Web::WebDriver::Response element_click(String) const; Web::WebDriver::Response element_send_keys(String, JsonValue) const;