From 46b2cb308d5a817da90d6bf6957067a9ce1914c3 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Mon, 21 Nov 2022 16:10:57 -0500 Subject: [PATCH] LibWeb+WebContent: Virtualize methods needed for WebDriver in PageClient WebDriver currently uses the WebContent::ConnectionFromClient IPC class directly for these features. To support headless-browser, WebDriver will instead need to rely on PageClient to provide these. --- Userland/Libraries/LibWeb/Page/Page.h | 15 +++++ Userland/Services/WebContent/PageHost.cpp | 67 ++++++++++++++++++- Userland/Services/WebContent/PageHost.h | 13 ++++ .../WebContent/WebDriverConnection.cpp | 32 ++++----- 4 files changed, 111 insertions(+), 16 deletions(-) diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index b00f2c6ca1..037f1a054c 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -17,10 +17,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -141,6 +143,15 @@ public: virtual CSS::PreferredColorScheme preferred_color_scheme() const = 0; virtual void paint(Gfx::IntRect const&, Gfx::Bitmap&) = 0; virtual void page_did_change_title(String const&) { } + virtual void page_did_request_navigate_back() { } + virtual void page_did_request_navigate_forward() { } + virtual void page_did_request_refresh() { } + virtual Gfx::IntSize page_did_request_resize_window(Gfx::IntSize const&) { return {}; } + virtual Gfx::IntPoint page_did_request_reposition_window(Gfx::IntPoint const&) { return {}; } + 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_start_loading(const AK::URL&) { } virtual void page_did_create_main_document() { } virtual void page_did_finish_loading(const AK::URL&) { } @@ -164,10 +175,14 @@ public: virtual void page_did_request_alert(String const&) { } virtual void page_did_request_confirm(String const&) { } virtual void page_did_request_prompt(String const&, String const&) { } + virtual void page_did_request_set_prompt_text(String const&) { } virtual void page_did_request_accept_dialog() { } virtual void page_did_request_dismiss_dialog() { } + virtual Vector page_did_request_all_cookies(AK::URL const&) { return {}; } + virtual Optional page_did_request_named_cookie(AK::URL const&, String const&) { return {}; } virtual String page_did_request_cookie(const AK::URL&, Cookie::Source) { return {}; } virtual void page_did_set_cookie(const AK::URL&, Cookie::ParsedCookie const&, Cookie::Source) { } + virtual void page_did_update_cookie(AK::URL const&, Web::Cookie::Cookie) { } virtual void page_did_update_resource_count(i32) { } virtual void page_did_close_browsing_context(HTML::BrowsingContext const&) { } diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index f110ef46db..6f61c1b0aa 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -92,7 +92,7 @@ void PageHost::set_window_size(Gfx::IntSize const& size) ErrorOr PageHost::connect_to_webdriver(String const& webdriver_ipc_path) { VERIFY(!m_webdriver); - m_webdriver = TRY(WebDriverConnection::connect(m_client, *this, webdriver_ipc_path)); + m_webdriver = TRY(WebDriverConnection::connect(*this, webdriver_ipc_path)); return {}; } @@ -163,6 +163,51 @@ void PageHost::page_did_change_title(String const& title) m_client.async_did_change_title(title); } +void PageHost::page_did_request_navigate_back() +{ + m_client.async_did_request_navigate_back(); +} + +void PageHost::page_did_request_navigate_forward() +{ + m_client.async_did_request_navigate_forward(); +} + +void PageHost::page_did_request_refresh() +{ + m_client.async_did_request_refresh(); +} + +Gfx::IntSize PageHost::page_did_request_resize_window(Gfx::IntSize const& size) +{ + return m_client.did_request_resize_window(size); +} + +Gfx::IntPoint PageHost::page_did_request_reposition_window(Gfx::IntPoint const& position) +{ + return m_client.did_request_reposition_window(position); +} + +void PageHost::page_did_request_restore_window() +{ + m_client.async_did_request_restore_window(); +} + +Gfx::IntRect PageHost::page_did_request_maximize_window() +{ + return m_client.did_request_maximize_window(); +} + +Gfx::IntRect PageHost::page_did_request_minimize_window() +{ + return m_client.did_request_minimize_window(); +} + +Gfx::IntRect PageHost::page_did_request_fullscreen_window() +{ + return m_client.did_request_fullscreen_window(); +} + void PageHost::page_did_request_scroll(i32 x_delta, i32 y_delta) { m_client.async_did_request_scroll(x_delta, y_delta); @@ -258,6 +303,11 @@ void PageHost::page_did_request_prompt(String const& message, String const& defa m_client.async_did_request_prompt(message, default_); } +void PageHost::page_did_request_set_prompt_text(String const& text) +{ + m_client.async_did_request_set_prompt_text(text); +} + void PageHost::prompt_closed(String response) { page().prompt_closed(move(response)); @@ -284,6 +334,16 @@ void PageHost::page_did_request_image_context_menu(Gfx::IntPoint const& content_ m_client.async_did_request_image_context_menu(content_position, url, target, modifiers, bitmap); } +Vector PageHost::page_did_request_all_cookies(URL const& url) +{ + return m_client.did_request_all_cookies(url); +} + +Optional PageHost::page_did_request_named_cookie(URL const& url, String const& name) +{ + return m_client.did_request_named_cookie(url, name); +} + String PageHost::page_did_request_cookie(const URL& url, Web::Cookie::Source source) { auto response = m_client.send_sync_but_allow_failure(move(url), static_cast(source)); @@ -299,6 +359,11 @@ void PageHost::page_did_set_cookie(const URL& url, Web::Cookie::ParsedCookie con m_client.async_did_set_cookie(url, cookie, static_cast(source)); } +void PageHost::page_did_update_cookie(URL const& url, Web::Cookie::Cookie cookie) +{ + m_client.async_did_update_cookie(url, move(cookie)); +} + void PageHost::page_did_update_resource_count(i32 count_waiting) { m_client.async_did_update_resource_count(count_waiting); diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h index 22ac903470..aadda02b5f 100644 --- a/Userland/Services/WebContent/PageHost.h +++ b/Userland/Services/WebContent/PageHost.h @@ -57,6 +57,15 @@ private: virtual void page_did_request_cursor_change(Gfx::StandardCursor) override; virtual void page_did_layout() override; virtual void page_did_change_title(String const&) override; + virtual void page_did_request_navigate_back() override; + virtual void page_did_request_navigate_forward() override; + virtual void page_did_request_refresh() override; + virtual Gfx::IntSize page_did_request_resize_window(Gfx::IntSize const&) override; + virtual Gfx::IntPoint page_did_request_reposition_window(Gfx::IntPoint const&) 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_scroll(i32, i32) override; virtual void page_did_request_scroll_to(Gfx::IntPoint const&) override; virtual void page_did_request_scroll_into_view(Gfx::IntRect const&) override; @@ -74,12 +83,16 @@ private: virtual void page_did_request_alert(String const&) override; virtual void page_did_request_confirm(String const&) override; virtual void page_did_request_prompt(String const&, String const&) override; + virtual void page_did_request_set_prompt_text(String const&) override; virtual void page_did_request_accept_dialog() override; virtual void page_did_request_dismiss_dialog() override; virtual void page_did_change_favicon(Gfx::Bitmap const&) override; virtual void page_did_request_image_context_menu(Gfx::IntPoint const&, const URL&, String const& target, unsigned modifiers, Gfx::Bitmap const*) override; + virtual Vector page_did_request_all_cookies(URL const&) override; + virtual Optional page_did_request_named_cookie(URL const&, String const&) override; virtual String page_did_request_cookie(const URL&, Web::Cookie::Source) override; virtual void page_did_set_cookie(const URL&, Web::Cookie::ParsedCookie const&, Web::Cookie::Source) override; + virtual void page_did_update_cookie(URL const&, Web::Cookie::Cookie) override; virtual void page_did_update_resource_count(i32) override; virtual void request_file(NonnullRefPtr&) override; diff --git a/Userland/Services/WebContent/WebDriverConnection.cpp b/Userland/Services/WebContent/WebDriverConnection.cpp index beb6aa53d0..315b1084fe 100644 --- a/Userland/Services/WebContent/WebDriverConnection.cpp +++ b/Userland/Services/WebContent/WebDriverConnection.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -385,7 +387,7 @@ Messages::WebDriverClient::BackResponse WebDriverConnection::back() TRY(handle_any_user_prompts()); // 3. Traverse the history by a delta –1 for the current browsing context. - m_web_content_client.async_did_request_navigate_back(); + m_page_client.page_did_request_navigate_back(); // FIXME: 4. If the previous step completed results in a pageHide event firing, wait until pageShow event fires or for the session page load timeout milliseconds to pass, whichever occurs sooner. // FIXME: 5. If the previous step completed by the session page load timeout being reached, and user prompts have been handled, return error with error code timeout. @@ -404,7 +406,7 @@ Messages::WebDriverClient::ForwardResponse WebDriverConnection::forward() TRY(handle_any_user_prompts()); // 3. Traverse the history by a delta 1 for the current browsing context. - m_web_content_client.async_did_request_navigate_forward(); + m_page_client.page_did_request_navigate_forward(); // FIXME: 4. If the previous step completed results in a pageHide event firing, wait until pageShow event fires or for the session page load timeout milliseconds to pass, whichever occurs sooner. // FIXME: 5. If the previous step completed by the session page load timeout being reached, and user prompts have been handled, return error with error code timeout. @@ -423,7 +425,7 @@ Messages::WebDriverClient::RefreshResponse WebDriverConnection::refresh() TRY(handle_any_user_prompts()); // 3. Initiate an overridden reload of the current top-level browsing context’s active document. - m_web_content_client.async_did_request_refresh(); + m_page_client.page_did_request_refresh(); // FIXME: 4. If url is special except for file: // FIXME: 1. Try to wait for navigation to complete. @@ -571,7 +573,7 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window 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. - auto size = m_web_content_client.did_request_resize_window({ *width, *height }); + auto size = m_page_client.page_did_request_resize_window({ *width, *height }); window_rect.set_size(size); } else { window_rect.set_size(m_page_client.page().window_size()); @@ -580,7 +582,7 @@ Messages::WebDriverClient::SetWindowRectResponse WebDriverConnection::set_window // 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. - auto position = m_web_content_client.did_request_reposition_window({ *x, *y }); + auto position = m_page_client.page_did_request_reposition_window({ *x, *y }); window_rect.set_location(position); } else { window_rect.set_location(m_page_client.page().window_position()); @@ -650,7 +652,7 @@ Messages::WebDriverClient::FullscreenWindowResponse WebDriverConnection::fullscr // 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 = m_web_content_client.did_request_fullscreen_window(); + auto rect = m_page_client.page_did_request_fullscreen_window(); // 6. Return success with data set to the WindowRect object for the current top-level browsing context. return serialize_rect(rect); @@ -1243,7 +1245,7 @@ Messages::WebDriverClient::GetAllCookiesResponse WebDriverConnection::get_all_co // 4. For each cookie in all associated cookies of the current browsing context’s active document: auto* document = m_page_client.page().top_level_browsing_context().active_document(); - for (auto const& cookie : m_web_content_client.did_request_all_cookies(document->url())) { + for (auto const& cookie : m_page_client.page_did_request_all_cookies(document->url())) { // 1. Let serialized cookie be the result of serializing cookie. auto serialized_cookie = serialize_cookie(cookie); @@ -1267,7 +1269,7 @@ Messages::WebDriverClient::GetNamedCookieResponse WebDriverConnection::get_named // 3. If the url variable name is equal to a cookie’s cookie name amongst all associated cookies of the current browsing context’s active document, return success with the serialized cookie as data. auto* document = m_page_client.page().top_level_browsing_context().active_document(); - if (auto cookie = m_web_content_client.did_request_named_cookie(document->url(), name); cookie.has_value()) { + if (auto cookie = m_page_client.page_did_request_named_cookie(document->url(), name); cookie.has_value()) { auto serialized_cookie = serialize_cookie(*cookie); return serialized_cookie; } @@ -1340,7 +1342,7 @@ Messages::WebDriverClient::AddCookieResponse WebDriverConnection::add_cookie(Jso } auto* document = m_page_client.page().top_level_browsing_context().active_document(); - m_web_content_client.async_did_set_cookie(document->url(), cookie, to_underlying(Web::Cookie::Source::Http)); + m_page_client.page_did_set_cookie(document->url(), cookie, Web::Cookie::Source::Http); // If there is an error during this step, return error with error code unable to set cookie. // NOTE: This probably should only apply to the actual setting of the cookie in the Browser, which cannot fail in our case. @@ -1469,7 +1471,7 @@ Messages::WebDriverClient::SendAlertTextResponse WebDriverConnection::send_alert } // 6. Perform user agent dependent steps to set the value of current user prompt’s text field to text. - m_web_content_client.async_did_request_set_prompt_text(move(text)); + m_page_client.page_did_request_set_prompt_text(move(text)); // 7. Return success with data null. return JsonValue {}; @@ -1593,7 +1595,7 @@ ErrorOr WebDriverConnection::handle_any_user_prompt 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. - m_web_content_client.async_did_request_restore_window(); + m_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: Implement timeouts. @@ -1607,7 +1609,7 @@ void WebDriverConnection::restore_the_window() Gfx::IntRect 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 = m_web_content_client.did_request_maximize_window(); + auto rect = m_page_client.page_did_request_maximize_window(); // Return when the window has completed the transition, or within an implementation-defined timeout. return rect; @@ -1617,7 +1619,7 @@ Gfx::IntRect WebDriverConnection::maximize_the_window() Gfx::IntRect WebDriverConnection::iconify_the_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. - auto rect = m_web_content_client.did_request_minimize_window(); + auto rect = m_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: Implement timeouts. @@ -1709,13 +1711,13 @@ void WebDriverConnection::delete_cookies(Optional const& name) // For each cookie among all associated cookies of the current browsing context’s active document, un the substeps of the first matching condition: auto* document = m_page_client.page().top_level_browsing_context().active_document(); - for (auto& cookie : m_web_content_client.did_request_all_cookies(document->url())) { + for (auto& cookie : m_page_client.page_did_request_all_cookies(document->url())) { // -> name is undefined // -> name is equal to cookie name if (!name.has_value() || name.value() == cookie.name) { // Set the cookie expiry time to a Unix timestamp in the past. cookie.expiry_time = Core::DateTime::from_timestamp(0); - m_web_content_client.async_did_update_cookie(document->url(), cookie); + m_page_client.page_did_update_cookie(document->url(), move(cookie)); } // -> Otherwise // Do nothing.