diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/Internals/BUILD.gn b/Meta/gn/secondary/Userland/Libraries/LibWeb/Internals/BUILD.gn index b68609ef1f..c97eb62c99 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/Internals/BUILD.gn +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/Internals/BUILD.gn @@ -1,5 +1,8 @@ source_set("Internals") { configs += [ "//Userland/Libraries/LibWeb:configs" ] deps = [ "//Userland/Libraries/LibWeb:all_generated" ] - sources = [ "Internals.cpp" ] + sources = [ + "Inspector.cpp", + "Internals.cpp", + ] } diff --git a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni index ca18948907..6ca47050da 100644 --- a/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni +++ b/Meta/gn/secondary/Userland/Libraries/LibWeb/idl_files.gni @@ -216,6 +216,7 @@ standard_idl_files = [ "//Userland/Libraries/LibWeb/HTML/WorkerLocation.idl", "//Userland/Libraries/LibWeb/HTML/WorkerNavigator.idl", "//Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl", + "//Userland/Libraries/LibWeb/Internals/Inspector.idl", "//Userland/Libraries/LibWeb/Internals/Internals.idl", "//Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.idl", "//Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserverEntry.idl", diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 70cbf5deda..94c64697dd 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -415,6 +415,7 @@ set(SOURCES Infra/ByteSequences.cpp Infra/JSON.cpp Infra/Strings.cpp + Internals/Inspector.cpp Internals/Internals.cpp IntersectionObserver/IntersectionObserver.cpp IntersectionObserver/IntersectionObserverEntry.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 9f75d87867..688b7d4365 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -482,6 +482,7 @@ class Performance; } namespace Web::Internals { +class Inspector; class Internals; } diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 49c34b89d4..0b368c0ea6 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -60,6 +60,7 @@ #include #include #include +#include #include #include #include @@ -781,8 +782,14 @@ WebIDL::ExceptionOr> Window::byte_length_ return JS::NonnullGCPtr { *m_byte_length_queuing_strategy_size_function }; } +static bool s_inspector_object_exposed = false; static bool s_internals_object_exposed = false; +void Window::set_inspector_object_exposed(bool exposed) +{ + s_inspector_object_exposed = exposed; +} + void Window::set_internals_object_exposed(bool exposed) { s_internals_object_exposed = exposed; @@ -798,6 +805,8 @@ WebIDL::ExceptionOr Window::initialize_web_interfaces(Badge(realm, realm), JS::default_attributes); if (s_internals_object_exposed) define_direct_property("internals", heap().allocate(realm, realm), JS::default_attributes); diff --git a/Userland/Libraries/LibWeb/HTML/Window.h b/Userland/Libraries/LibWeb/HTML/Window.h index c386af80f4..ddf20b0c12 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.h +++ b/Userland/Libraries/LibWeb/HTML/Window.h @@ -196,6 +196,7 @@ public: HighResolutionTime::DOMHighResTimeStamp get_last_activation_timestamp() const { return m_last_activation_timestamp; } void set_last_activation_timestamp(HighResolutionTime::DOMHighResTimeStamp timestamp) { m_last_activation_timestamp = timestamp; } + static void set_inspector_object_exposed(bool); static void set_internals_object_exposed(bool); [[nodiscard]] OrderedHashMap> document_tree_child_navigable_target_name_property_set(); diff --git a/Userland/Libraries/LibWeb/Internals/Inspector.cpp b/Userland/Libraries/LibWeb/Internals/Inspector.cpp new file mode 100644 index 0000000000..12783c3e9f --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Inspector.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Web::Internals { + +JS_DEFINE_ALLOCATOR(Inspector); + +Inspector::Inspector(JS::Realm& realm) + : Bindings::PlatformObject(realm) +{ +} + +Inspector::~Inspector() = default; + +void Inspector::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + Object::set_prototype(&Bindings::ensure_web_prototype(realm, "Inspector")); +} + +void Inspector::inspector_loaded() +{ + if (auto* page = global_object().browsing_context()->page()) + page->client().inspector_did_load(); +} + +void Inspector::inspect_dom_node(i32 node_id, Optional const& pseudo_element) +{ + if (auto* page = global_object().browsing_context()->page()) { + page->client().inspector_did_select_dom_node(node_id, pseudo_element.map([](auto value) { + VERIFY(value < to_underlying(Web::CSS::Selector::PseudoElement::PseudoElementCount)); + return static_cast(value); + })); + } +} + +} diff --git a/Userland/Libraries/LibWeb/Internals/Inspector.h b/Userland/Libraries/LibWeb/Internals/Inspector.h new file mode 100644 index 0000000000..86d053c7ed --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Inspector.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::Internals { + +class Inspector final : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(Inspector, Bindings::PlatformObject); + JS_DECLARE_ALLOCATOR(Inspector); + +public: + virtual ~Inspector() override; + + void inspector_loaded(); + void inspect_dom_node(i32 node_id, Optional const& pseudo_element); + +private: + explicit Inspector(JS::Realm&); + + virtual void initialize(JS::Realm&) override; +}; + +} diff --git a/Userland/Libraries/LibWeb/Internals/Inspector.idl b/Userland/Libraries/LibWeb/Internals/Inspector.idl new file mode 100644 index 0000000000..e514987456 --- /dev/null +++ b/Userland/Libraries/LibWeb/Internals/Inspector.idl @@ -0,0 +1,6 @@ +[Exposed=Nobody] interface Inspector { + + undefined inspectorLoaded(); + undefined inspectDOMNode(long nodeID, optional long pseudoElement); + +}; diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index a68c7a5c77..003bf234eb 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -260,6 +261,9 @@ public: virtual void page_did_insert_clipboard_entry([[maybe_unused]] String data, [[maybe_unused]] String presentation_style, [[maybe_unused]] String mime_type) { } + virtual void inspector_did_load() { } + virtual void inspector_did_select_dom_node([[maybe_unused]] i32 node_id, [[maybe_unused]] Optional const& pseudo_element) { } + protected: virtual ~PageClient() = default; }; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 87b044973b..1cf11d88ef 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -202,6 +202,7 @@ libweb_js_bindings(HTML/WorkerGlobalScope) libweb_js_bindings(HTML/WorkerLocation) libweb_js_bindings(HTML/WorkerNavigator) libweb_js_bindings(HighResolutionTime/Performance) +libweb_js_bindings(Internals/Inspector) libweb_js_bindings(Internals/Internals) libweb_js_bindings(IntersectionObserver/IntersectionObserver) libweb_js_bindings(IntersectionObserver/IntersectionObserverEntry) diff --git a/Userland/Libraries/LibWebView/ViewImplementation.cpp b/Userland/Libraries/LibWebView/ViewImplementation.cpp index 26cd98a458..2df40f3af8 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.cpp +++ b/Userland/Libraries/LibWebView/ViewImplementation.cpp @@ -383,4 +383,9 @@ void ViewImplementation::use_native_user_style_sheet() set_user_style_sheet(MUST(String::from_utf8(native_stylesheet_source))); } +void ViewImplementation::enable_inspector_prototype() +{ + client().async_enable_inspector_prototype(); +} + } diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index 6c8bb14d52..5bdabd99cb 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -106,6 +106,8 @@ public: // native GUI widgets as possible. void use_native_user_style_sheet(); + void enable_inspector_prototype(); + Function on_did_layout; Function on_ready_to_paint; Function on_new_tab; @@ -161,6 +163,8 @@ public: Function on_text_test_finish; Function on_theme_color_change; Function on_insert_clipboard_entry; + Function on_inspector_loaded; + Function const&)> on_inspector_selected_dom_node; virtual Gfx::IntRect viewport_rect() const = 0; virtual Gfx::IntPoint to_content_position(Gfx::IntPoint widget_position) const = 0; diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp index 1033fd3697..5a1ece2f39 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.cpp +++ b/Userland/Libraries/LibWebView/WebContentClient.cpp @@ -402,4 +402,16 @@ void WebContentClient::did_insert_clipboard_entry(String const& data, String con m_view.on_insert_clipboard_entry(data, presentation_style, mime_type); } +void WebContentClient::inspector_did_load() +{ + if (m_view.on_inspector_loaded) + m_view.on_inspector_loaded(); +} + +void WebContentClient::inspector_did_select_dom_node(i32 node_id, Optional const& pseudo_element) +{ + if (m_view.on_inspector_selected_dom_node) + m_view.on_inspector_selected_dom_node(node_id, pseudo_element); +} + } diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h index 41e21e563a..194d1682f8 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.h +++ b/Userland/Libraries/LibWebView/WebContentClient.h @@ -86,6 +86,8 @@ private: virtual void did_finish_text_test() override; virtual void did_change_theme_color(Gfx::Color color) override; virtual void did_insert_clipboard_entry(String const& data, String const& presentation_style, String const& mime_type) override; + virtual void inspector_did_load() override; + virtual void inspector_did_select_dom_node(i32 node_id, Optional const& pseudo_element) override; ViewImplementation& m_view; }; diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index 3af096a068..0e8ec1a875 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -929,4 +929,9 @@ void ConnectionFromClient::inspect_accessibility_tree() } } +void ConnectionFromClient::enable_inspector_prototype() +{ + Web::HTML::Window::set_inspector_object_exposed(true); +} + } diff --git a/Userland/Services/WebContent/ConnectionFromClient.h b/Userland/Services/WebContent/ConnectionFromClient.h index b989f5c881..d3aa1981a0 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.h +++ b/Userland/Services/WebContent/ConnectionFromClient.h @@ -106,6 +106,8 @@ private: virtual void set_user_style(String const&) override; + virtual void enable_inspector_prototype() override; + virtual Messages::WebContentServer::TakeDocumentScreenshotResponse take_document_screenshot() override; virtual Messages::WebContentServer::GetLocalStorageEntriesResponse get_local_storage_entries() override; diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index d8078a71b4..e58bd402e2 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -503,4 +503,14 @@ void PageHost::page_did_insert_clipboard_entry(String data, String presentation_ m_client.async_did_insert_clipboard_entry(move(data), move(presentation_style), move(mime_type)); } +void PageHost::inspector_did_load() +{ + m_client.async_inspector_did_load(); +} + +void PageHost::inspector_did_select_dom_node(i32 node_id, Optional const& pseudo_element) +{ + m_client.async_inspector_did_select_dom_node(node_id, pseudo_element); +} + } diff --git a/Userland/Services/WebContent/PageHost.h b/Userland/Services/WebContent/PageHost.h index b47ee99ab5..9425f473e6 100644 --- a/Userland/Services/WebContent/PageHost.h +++ b/Userland/Services/WebContent/PageHost.h @@ -121,6 +121,8 @@ private: virtual void page_did_finish_text_test() override; virtual void page_did_change_theme_color(Gfx::Color color) override; virtual void page_did_insert_clipboard_entry(String data, String presentation_style, String mime_type) override; + virtual void inspector_did_load() override; + virtual void inspector_did_select_dom_node(i32 node_id, Optional const& pseudo_element) override; explicit PageHost(ConnectionFromClient&); diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index 1f44c60ad3..c35fc5ef06 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -69,4 +70,7 @@ endpoint WebContentClient did_finish_text_test() =| + inspector_did_load() =| + inspector_did_select_dom_node(i32 node_id, Optional pseudo_element) =| + } diff --git a/Userland/Services/WebContent/WebContentServer.ipc b/Userland/Services/WebContent/WebContentServer.ipc index 72a23fbb38..bee54d22df 100644 --- a/Userland/Services/WebContent/WebContentServer.ipc +++ b/Userland/Services/WebContent/WebContentServer.ipc @@ -86,4 +86,6 @@ endpoint WebContentServer toggle_media_controls_state() =| set_user_style(String source) =| + + enable_inspector_prototype() =| }