diff --git a/Libraries/LibWebView/Application.cpp b/Libraries/LibWebView/Application.cpp index 8558900d434..3da2e29b4ce 100644 --- a/Libraries/LibWebView/Application.cpp +++ b/Libraries/LibWebView/Application.cpp @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -68,6 +70,7 @@ void Application::initialize(Main::Arguments const& arguments, URL::URL new_tab_ bool allow_popups = false; bool disable_scripting = false; bool disable_sql_database = false; + Optional devtools_port; Optional debug_process; Optional profile_process; Optional webdriver_content_ipc_path; @@ -97,6 +100,7 @@ void Application::initialize(Main::Arguments const& arguments, URL::URL new_tab_ args_parser.add_option(debug_process, "Wait for a debugger to attach to the given process name (WebContent, RequestServer, etc.)", "debug-process", 0, "process-name"); args_parser.add_option(profile_process, "Enable callgrind profiling of the given process name (WebContent, RequestServer, etc.)", "profile-process", 0, "process-name"); args_parser.add_option(webdriver_content_ipc_path, "Path to WebDriver IPC for WebContent", "webdriver-content-path", 0, "path", Core::ArgsParser::OptionHideMode::CommandLineAndMarkdown); + args_parser.add_option(devtools_port, "Set the Firefox DevTools port (EXPERIMENTAL)", "devtools", 0, "port"); args_parser.add_option(log_all_js_exceptions, "Log all JavaScript exceptions", "log-all-js-exceptions"); args_parser.add_option(enable_idl_tracing, "Enable IDL tracing", "enable-idl-tracing"); args_parser.add_option(enable_http_cache, "Enable HTTP cache", "enable-http-cache"); @@ -156,6 +160,7 @@ void Application::initialize(Main::Arguments const& arguments, URL::URL new_tab_ ? DNSSettings(DNSOverTLS(dns_server_address.release_value(), *dns_server_port)) : DNSSettings(DNSOverUDP(dns_server_address.release_value(), *dns_server_port))) : SystemDNS {}), + .devtools_port = devtools_port, }; if (webdriver_content_ipc_path.has_value()) @@ -190,6 +195,7 @@ ErrorOr Application::launch_services() { TRY(launch_request_server()); TRY(launch_image_decoder_server()); + TRY(launch_devtools_server()); return {}; } @@ -228,6 +234,13 @@ ErrorOr Application::launch_image_decoder_server() return {}; } +ErrorOr Application::launch_devtools_server() +{ + if (m_chrome_options.devtools_port.has_value()) + m_devtools = TRY(DevTools::DevToolsServer::create(*this, *m_chrome_options.devtools_port)); + return {}; +} + int Application::execute() { int ret = m_event_loop.exec(); @@ -315,4 +328,60 @@ ErrorOr Application::path_for_downloaded_file(StringView file) cons return LexicalPath::join(downloads_directory, file); } +void Application::refresh_tab_list() +{ + if (!m_devtools) + return; + m_devtools->refresh_tab_list(); +} + +Vector Application::tab_list() const +{ + Vector tabs; + + ViewImplementation::for_each_view([&](ViewImplementation& view) { + tabs.empend(view.view_id(), view.title(), view.url().to_byte_string()); + return IterationDecision::Continue; + }); + + return tabs; +} + +Vector Application::css_property_list() const +{ + Vector property_list; + + for (auto i = to_underlying(Web::CSS::first_property_id); i <= to_underlying(Web::CSS::last_property_id); ++i) { + auto property_id = static_cast(i); + + DevTools::CSSProperty property; + property.name = Web::CSS::string_from_property_id(property_id).to_string().to_byte_string(); + property.is_inherited = Web::CSS::is_inherited_property(property_id); + property_list.append(move(property)); + } + + return property_list; +} + +void Application::inspect_tab(DevTools::TabDescription const& description, DevTools::DevToolsDelegate::OnTabInspectionComplete on_complete) const +{ + auto view = ViewImplementation::find_view_by_id(description.id); + if (!view.has_value()) { + on_complete(Error::from_string_literal("Unable to locate tab")); + return; + } + + view->on_received_dom_tree = [&view = *view, on_complete = move(on_complete)](ByteString const& dom_tree) { + view.on_received_dom_tree = nullptr; + + if (auto parsed_tree = JsonValue::from_string(dom_tree); parsed_tree.is_error()) { + on_complete(parsed_tree.release_error()); + } else { + on_complete(parsed_tree.release_value()); + } + }; + + view->inspect_dom_tree(); +} + } diff --git a/Libraries/LibWebView/Application.h b/Libraries/LibWebView/Application.h index 46a473cfe8e..14febc24948 100644 --- a/Libraries/LibWebView/Application.h +++ b/Libraries/LibWebView/Application.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -23,7 +25,7 @@ namespace WebView { -class Application { +class Application : public DevTools::DevToolsDelegate { AK_MAKE_NONCOPYABLE(Application); public: @@ -59,6 +61,8 @@ public: ErrorOr path_for_downloaded_file(StringView file) const; + void refresh_tab_list(); + protected: template ApplicationType> static NonnullOwnPtr create(Main::Arguments& arguments, URL::URL new_tab_page_url) @@ -83,6 +87,11 @@ private: ErrorOr launch_request_server(); ErrorOr launch_image_decoder_server(); + ErrorOr launch_devtools_server(); + + virtual Vector tab_list() const override; + virtual Vector css_property_list() const override; + virtual void inspect_tab(DevTools::TabDescription const&, DevTools::DevToolsDelegate::OnTabInspectionComplete) const override; static Application* s_the; @@ -100,6 +109,8 @@ private: Core::EventLoop m_event_loop; ProcessManager m_process_manager; bool m_in_shutdown { false }; + + OwnPtr m_devtools; } SWIFT_IMMORTAL_REFERENCE; } diff --git a/Libraries/LibWebView/CMakeLists.txt b/Libraries/LibWebView/CMakeLists.txt index e62a04c7400..edab69343fa 100644 --- a/Libraries/LibWebView/CMakeLists.txt +++ b/Libraries/LibWebView/CMakeLists.txt @@ -71,7 +71,7 @@ set(GENERATED_SOURCES ) serenity_lib(LibWebView webview) -target_link_libraries(LibWebView PRIVATE LibCore LibFileSystem LibGfx LibImageDecoderClient LibIPC LibRequests LibJS LibWeb LibUnicode LibURL LibSyntax) +target_link_libraries(LibWebView PRIVATE LibCore LibDevTools LibFileSystem LibGfx LibImageDecoderClient LibIPC LibRequests LibJS LibWeb LibUnicode LibURL LibSyntax) if (APPLE) target_link_libraries(LibWebView PRIVATE LibThreading) diff --git a/Libraries/LibWebView/Options.h b/Libraries/LibWebView/Options.h index 5c0de4f2760..bd023288ce5 100644 --- a/Libraries/LibWebView/Options.h +++ b/Libraries/LibWebView/Options.h @@ -71,6 +71,7 @@ struct ChromeOptions { Optional profile_helper_process {}; Optional webdriver_content_ipc_path {}; DNSSettings dns_settings { SystemDNS {} }; + Optional devtools_port; }; enum class IsLayoutTestMode {