From 202b2be1f2eda0042dd6771f339b1ab12a4ca406 Mon Sep 17 00:00:00 2001 From: Tobias Christiansen Date: Thu, 20 Oct 2022 12:02:47 +0200 Subject: [PATCH] WebContent+Friends: Add IPC and plumbing for WebDriver endpoint To use the `GET /session/{id}/element/{id}/css/{property name}` WebDriver endpoint, two new IPC calls through the Browser are implemented: - get_active_documents_type returns the type of the active document, which is either "xml" or "html" - get_computed_value_for_element returns the computed CSS value (as String) for the given element and CSS property name --- .../Applications/Browser/BrowserWindow.cpp | 8 ++++ Userland/Applications/Browser/Tab.h | 2 + .../LibWebView/OutOfProcessWebView.cpp | 10 +++++ .../LibWebView/OutOfProcessWebView.h | 2 + .../WebContent/ConnectionFromClient.cpp | 44 +++++++++++++++++++ .../WebContent/ConnectionFromClient.h | 2 + .../Services/WebContent/WebContentServer.ipc | 2 + 7 files changed, 70 insertions(+) diff --git a/Userland/Applications/Browser/BrowserWindow.cpp b/Userland/Applications/Browser/BrowserWindow.cpp index 3c9e851652..da874d8c93 100644 --- a/Userland/Applications/Browser/BrowserWindow.cpp +++ b/Userland/Applications/Browser/BrowserWindow.cpp @@ -598,6 +598,14 @@ void BrowserWindow::create_new_tab(URL url, bool activate) return active_tab().view().get_element_property(element_id, name); }; + new_tab.on_get_active_documents_type = [this]() { + return active_tab().view().get_active_documents_type(); + }; + + new_tab.on_get_computed_value_for_element = [this](i32 element_id, String const& property_name) { + return active_tab().view().get_computed_value_for_element(element_id, property_name); + }; + new_tab.load(url); dbgln_if(SPAM_DEBUG, "Added new tab {:p}, loading {}", &new_tab, url); diff --git a/Userland/Applications/Browser/Tab.h b/Userland/Applications/Browser/Tab.h index 38914b8644..7cb43124a5 100644 --- a/Userland/Applications/Browser/Tab.h +++ b/Userland/Applications/Browser/Tab.h @@ -72,6 +72,8 @@ public: Function>(i32 start_node_id, String const&)> on_query_selector_all; Function(i32 element_id, String const&)> on_get_element_attribute; Function(i32 element_id, String const&)> on_get_element_property; + Function on_get_active_documents_type; + Function on_get_computed_value_for_element; enum class InspectorTarget { Document, diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp index 8c719943a7..a50d6fabcc 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.cpp @@ -535,6 +535,16 @@ Optional OutOfProcessWebView::get_element_property(i32 element_id, Strin return client().get_element_property(element_id, name); } +String OutOfProcessWebView::get_active_documents_type() +{ + return client().get_active_documents_type(); +} + +String OutOfProcessWebView::get_computed_value_for_element(i32 element_id, String const& property_name) +{ + return client().get_computed_value_for_element(element_id, property_name); +} + void OutOfProcessWebView::set_content_filters(Vector filters) { client().async_set_content_filters(filters); diff --git a/Userland/Libraries/LibWebView/OutOfProcessWebView.h b/Userland/Libraries/LibWebView/OutOfProcessWebView.h index da6846d7e1..a684433cb6 100644 --- a/Userland/Libraries/LibWebView/OutOfProcessWebView.h +++ b/Userland/Libraries/LibWebView/OutOfProcessWebView.h @@ -62,6 +62,8 @@ public: Optional> query_selector_all(i32 start_node_id, String const& selector); Optional get_element_attribute(i32 element_id, String const& name); Optional get_element_property(i32 element_id, String const& name); + String get_active_documents_type(); + String get_computed_value_for_element(i32 element_id, String const& property_name); void set_content_filters(Vector); void set_proxy_mappings(Vector proxies, HashMap mappings); diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 73846aade6..c97d52c99f 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -517,6 +518,49 @@ Messages::WebContentServer::GetElementPropertyResponse ConnectionFromClient::get return { string_or_error.release_value() }; } +Messages::WebContentServer::GetActiveDocumentsTypeResponse ConnectionFromClient::get_active_documents_type() +{ + auto* active_document = page().top_level_browsing_context().active_document(); + + if (!active_document) + return { "" }; + + auto type = active_document->document_type(); + + switch (type) { + case Web::DOM::Document::Type::HTML: + return { "html" }; + break; + case Web::DOM::Document::Type::XML: + return { "xml" }; + break; + } + + return { "" }; +} + +Messages::WebContentServer::GetComputedValueForElementResponse ConnectionFromClient::get_computed_value_for_element(i32 element_id, String const& property_name) +{ + auto* node = Web::DOM::Node::from_id(element_id); + if (!node) + return { "" }; + + if (!node->is_element()) + return { "" }; + + auto& element = verify_cast(*node); + + auto property_id = Web::CSS::property_id_from_string(property_name); + + auto computed_values = element.computed_css_values(); + if (!computed_values) + return { "" }; + + auto style_value = computed_values->property(property_id); + + return { style_value->to_string() }; +} + Messages::WebContentServer::GetSelectedTextResponse ConnectionFromClient::get_selected_text() { return page().focused_context().selected_text(); diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index 7406a98536..c9942b42f5 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -83,6 +83,8 @@ private: virtual Messages::WebContentServer::QuerySelectorAllResponse query_selector_all(i32 start_node_id, String const& selector) 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; + virtual Messages::WebContentServer::GetActiveDocumentsTypeResponse get_active_documents_type() override; + virtual Messages::WebContentServer::GetComputedValueForElementResponse get_computed_value_for_element(i32 element_id, String const& property_name) override; virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override; virtual Messages::WebContentServer::GetSessionStorageEntriesResponse get_session_storage_entries() override; diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index 1f9bd696ff..b8bd3c7952 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -41,6 +41,8 @@ endpoint WebContentServer query_selector_all(i32 start_node_id, String selector) => (Optional> elements_ids) get_element_attribute(i32 element_id, String name) => (Optional attribute) get_element_property(i32 element_id, String name) => (Optional property) + get_active_documents_type() => (String type) + get_computed_value_for_element(i32 element_id, String property_name) => (String computed_value) run_javascript(String js_source) =|