From 424e80ee75b50d7824a913351e419b9384c96c1f Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Fri, 4 Nov 2022 15:49:15 -0400 Subject: [PATCH] LibWebView+WebContent: Add an IPC to scroll an element into view Note that even though there is no response, this IPC has to be synchronous to allow all scroll events to trigger before returning to the calling WebDriver process. --- .../LibWebView/OutOfProcessWebView.cpp | 5 +++++ .../LibWebView/OutOfProcessWebView.h | 1 + .../WebContent/ConnectionFromClient.cpp | 20 +++++++++++++++++++ .../WebContent/ConnectionFromClient.h | 1 + .../Services/WebContent/WebContentServer.ipc | 1 + 5 files changed, 28 insertions(+) diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp index 464eba8cb9..cb088c4f6d 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp @@ -530,6 +530,11 @@ Optional> OutOfProcessWebView::query_selector_all(i32 start_node_id, return client().query_selector_all(start_node_id, selector); } +void OutOfProcessWebView::scroll_element_into_view(i32 element_id) +{ + return client().scroll_element_into_view(element_id); +} + bool OutOfProcessWebView::is_element_selected(i32 element_id) { return client().is_element_selected(element_id); diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.h b/Userland/Libraries/LibWebView/OutOfProcessWebView.h index 9d2e072223..bc03b5b346 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.h @@ -65,6 +65,7 @@ public: Optional get_document_element(); Optional> query_selector_all(i32 start_node_id, String const& selector); + void scroll_element_into_view(i32 element_id); bool is_element_selected(i32 element_id); Optional get_element_attribute(i32 element_id, String const& name); Optional get_element_property(i32 element_id, String const& name); diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 25dee36c87..ef08c17743 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -503,6 +503,26 @@ static Optional find_element_by_id(i32 element_id) return verify_cast(*node); } +// https://w3c.github.io/webdriver/#dfn-scrolls-into-view +void ConnectionFromClient::scroll_element_into_view(i32 element_id) +{ + auto element = find_element_by_id(element_id); + if (!element.has_value()) + return; + + // 1. Let options be the following ScrollIntoViewOptions: + Web::DOM::ScrollIntoViewOptions options {}; + // Logical scroll position "block" + // "end" + options.block = Web::Bindings::ScrollLogicalPosition::End; + // Logical scroll position "inline" + // "nearest" + options.inline_ = Web::Bindings::ScrollLogicalPosition::Nearest; + + // 2. Run Function.[[Call]](scrollIntoView, options) with element as the this value. + element->scroll_into_view(options); +} + Messages::WebContentServer::IsElementSelectedResponse ConnectionFromClient::is_element_selected(i32 element_id) { auto element = find_element_by_id(element_id); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 07d65bb16a..7130f9644d 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -85,6 +85,7 @@ private: virtual Messages::WebContentServer::GetDocumentElementResponse get_document_element() override; virtual Messages::WebContentServer::QuerySelectorAllResponse query_selector_all(i32 start_node_id, String const& selector) override; + virtual void scroll_element_into_view(i32 element_id) override; virtual Messages::WebContentServer::IsElementSelectedResponse is_element_selected(i32 element_id) override; virtual Messages::WebContentServer::GetElementAttributeResponse get_element_attribute(i32 element_id, String const& name) override; virtual Messages::WebContentServer::GetElementPropertyResponse get_element_property(i32 element_id, String const& name) override; diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index e5b4a4aa6e..51c6fbf3bd 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -42,6 +42,7 @@ endpoint WebContentServer get_document_element() => (Optional node_id) query_selector_all(i32 start_node_id, String selector) => (Optional> elements_ids) + scroll_element_into_view(i32 element_id) => () is_element_selected(i32 element_id) => (bool selected) get_element_attribute(i32 element_id, String name) => (Optional attribute) get_element_property(i32 element_id, String name) => (Optional property)