mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-05 15:49:11 +00:00
LibWebView+WebContent: Begin supporting the DevTools JavaScript console
This supports evaluating the script and replying with the result. We currently serialize JS objects to a string, but we will need to support dynamic interaction with the objects over IPC. This does not yet support sending console messages to DevTools.
This commit is contained in:
parent
6d33b70e61
commit
32bc2dc7b6
Notes:
github-actions[bot]
2025-02-28 12:09:35 +00:00
Author: https://github.com/trflynn89
Commit: 32bc2dc7b6
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3686
10 changed files with 101 additions and 2 deletions
|
@ -417,4 +417,20 @@ void Application::clear_highlighted_dom_node(DevTools::TabDescription const& des
|
||||||
view->clear_highlighted_dom_node();
|
view->clear_highlighted_dom_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::evaluate_javascript(DevTools::TabDescription const& description, String script, OnScriptEvaluationComplete 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_js_console_result = [&view = *view, on_complete = move(on_complete)](JsonValue result) {
|
||||||
|
view.on_received_js_console_result = nullptr;
|
||||||
|
on_complete(move(result));
|
||||||
|
};
|
||||||
|
|
||||||
|
view->js_console_input(move(script));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,6 +96,7 @@ private:
|
||||||
virtual void clear_inspected_dom_node(DevTools::TabDescription const&) const override;
|
virtual void clear_inspected_dom_node(DevTools::TabDescription const&) const override;
|
||||||
virtual void highlight_dom_node(DevTools::TabDescription const&, Web::UniqueNodeID, Optional<Web::CSS::Selector::PseudoElement::Type>) const override;
|
virtual void highlight_dom_node(DevTools::TabDescription const&, Web::UniqueNodeID, Optional<Web::CSS::Selector::PseudoElement::Type>) const override;
|
||||||
virtual void clear_highlighted_dom_node(DevTools::TabDescription const&) const override;
|
virtual void clear_highlighted_dom_node(DevTools::TabDescription const&) const override;
|
||||||
|
virtual void evaluate_javascript(DevTools::TabDescription const&, String, OnScriptEvaluationComplete) const override;
|
||||||
|
|
||||||
static Application* s_the;
|
static Application* s_the;
|
||||||
|
|
||||||
|
|
|
@ -215,6 +215,7 @@ public:
|
||||||
Function<void(Web::UniqueNodeID)> on_received_hovered_node_id;
|
Function<void(Web::UniqueNodeID)> on_received_hovered_node_id;
|
||||||
Function<void(Optional<Web::UniqueNodeID> const& node_id)> on_finshed_editing_dom_node;
|
Function<void(Optional<Web::UniqueNodeID> const& node_id)> on_finshed_editing_dom_node;
|
||||||
Function<void(String const&)> on_received_dom_node_html;
|
Function<void(String const&)> on_received_dom_node_html;
|
||||||
|
Function<void(JsonValue)> on_received_js_console_result;
|
||||||
Function<void(i32 message_id)> on_received_console_message;
|
Function<void(i32 message_id)> on_received_console_message;
|
||||||
Function<void(i32 start_index, Vector<String> const& message_types, Vector<String> const& messages)> on_received_console_messages;
|
Function<void(i32 start_index, Vector<String> const& message_types, Vector<String> const& messages)> on_received_console_messages;
|
||||||
Function<void(i32 count_waiting)> on_resource_status_change;
|
Function<void(i32 count_waiting)> on_resource_status_change;
|
||||||
|
|
|
@ -366,6 +366,14 @@ void WebContentClient::did_get_internal_page_info(u64 page_id, WebView::PageInfo
|
||||||
view->did_receive_internal_page_info({}, type, info);
|
view->did_receive_internal_page_info({}, type, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebContentClient::did_execute_js_console_input(u64 page_id, JsonValue const& result)
|
||||||
|
{
|
||||||
|
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||||
|
if (view->on_received_js_console_result)
|
||||||
|
view->on_received_js_console_result(move(const_cast<JsonValue&>(result)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WebContentClient::did_output_js_console_message(u64 page_id, i32 message_index)
|
void WebContentClient::did_output_js_console_message(u64 page_id, i32 message_index)
|
||||||
{
|
{
|
||||||
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
if (auto view = view_for_page_id(page_id); view.has_value()) {
|
||||||
|
|
|
@ -79,6 +79,7 @@ private:
|
||||||
virtual void did_get_dom_node_html(u64 page_id, String const& html) override;
|
virtual void did_get_dom_node_html(u64 page_id, String const& html) override;
|
||||||
virtual void did_take_screenshot(u64 page_id, Gfx::ShareableBitmap const& screenshot) override;
|
virtual void did_take_screenshot(u64 page_id, Gfx::ShareableBitmap const& screenshot) override;
|
||||||
virtual void did_get_internal_page_info(u64 page_id, PageInfoType, String const&) override;
|
virtual void did_get_internal_page_info(u64 page_id, PageInfoType, String const&) override;
|
||||||
|
virtual void did_execute_js_console_input(u64 page_id, JsonValue const&) override;
|
||||||
virtual void did_output_js_console_message(u64 page_id, i32 message_index) override;
|
virtual void did_output_js_console_message(u64 page_id, i32 message_index) override;
|
||||||
virtual void did_get_js_console_messages(u64 page_id, i32 start_index, Vector<String> const& message_types, Vector<String> const& messages) override;
|
virtual void did_get_js_console_messages(u64 page_id, i32 start_index, Vector<String> const& message_types, Vector<String> const& messages) override;
|
||||||
virtual void did_change_favicon(u64 page_id, Gfx::ShareableBitmap const&) override;
|
virtual void did_change_favicon(u64 page_id, Gfx::ShareableBitmap const&) override;
|
||||||
|
|
|
@ -30,7 +30,7 @@ target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${CMAKE_CU
|
||||||
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}>)
|
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}>)
|
||||||
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}/Services/>)
|
target_include_directories(webcontentservice PUBLIC $<BUILD_INTERFACE:${LADYBIRD_SOURCE_DIR}/Services/>)
|
||||||
|
|
||||||
target_link_libraries(webcontentservice PUBLIC LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibMedia LibWeb LibWebSocket LibRequests LibWebView LibImageDecoderClient LibGC)
|
target_link_libraries(webcontentservice PUBLIC LibCore LibCrypto LibFileSystem LibGfx LibIPC LibJS LibMain LibMedia LibWeb LibWebSocket LibRequests LibWebView LibImageDecoderClient LibGC)
|
||||||
target_link_libraries(webcontentservice PRIVATE OpenSSL::Crypto OpenSSL::SSL)
|
target_link_libraries(webcontentservice PRIVATE OpenSSL::Crypto OpenSSL::SSL)
|
||||||
|
|
||||||
if (ENABLE_QT)
|
if (ENABLE_QT)
|
||||||
|
|
|
@ -4,7 +4,13 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
|
#include <AK/MemoryStream.h>
|
||||||
|
#include <LibJS/Print.h>
|
||||||
|
#include <LibJS/Runtime/BigInt.h>
|
||||||
#include <LibJS/Runtime/Realm.h>
|
#include <LibJS/Runtime/Realm.h>
|
||||||
|
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
|
#include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
|
||||||
#include <WebContent/DevToolsConsoleClient.h>
|
#include <WebContent/DevToolsConsoleClient.h>
|
||||||
|
@ -29,9 +35,67 @@ DevToolsConsoleClient::DevToolsConsoleClient(JS::Realm& realm, JS::Console& cons
|
||||||
|
|
||||||
DevToolsConsoleClient::~DevToolsConsoleClient() = default;
|
DevToolsConsoleClient::~DevToolsConsoleClient() = default;
|
||||||
|
|
||||||
|
// https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html#grips
|
||||||
|
static JsonValue serialize_js_value(JS::Realm& realm, JS::Value value)
|
||||||
|
{
|
||||||
|
auto& vm = realm.vm();
|
||||||
|
|
||||||
|
auto serialize_type = [](StringView type) {
|
||||||
|
JsonObject serialized;
|
||||||
|
serialized.set("type"sv, type);
|
||||||
|
return serialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (value.is_undefined())
|
||||||
|
return serialize_type("undefined"sv);
|
||||||
|
|
||||||
|
if (value.is_null())
|
||||||
|
return serialize_type("null"sv);
|
||||||
|
|
||||||
|
if (value.is_boolean())
|
||||||
|
return value.as_bool();
|
||||||
|
|
||||||
|
if (value.is_string())
|
||||||
|
return value.as_string().utf8_string();
|
||||||
|
|
||||||
|
if (value.is_number()) {
|
||||||
|
if (value.is_nan())
|
||||||
|
return serialize_type("NaN"sv);
|
||||||
|
if (value.is_positive_infinity())
|
||||||
|
return serialize_type("Infinity"sv);
|
||||||
|
if (value.is_negative_infinity())
|
||||||
|
return serialize_type("-Infinity"sv);
|
||||||
|
if (value.is_negative_zero())
|
||||||
|
return serialize_type("-0"sv);
|
||||||
|
return value.as_double();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_bigint()) {
|
||||||
|
auto serialized = serialize_type("BigInt"sv);
|
||||||
|
serialized.set("text"sv, MUST(value.as_bigint().big_integer().to_base(10)));
|
||||||
|
return serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.is_symbol())
|
||||||
|
return MUST(value.as_symbol().descriptive_string());
|
||||||
|
|
||||||
|
// FIXME: Handle serialization of object grips. For now, we stringify the object.
|
||||||
|
if (value.is_object()) {
|
||||||
|
Web::HTML::TemporaryExecutionContext execution_context { realm };
|
||||||
|
AllocatingMemoryStream stream;
|
||||||
|
|
||||||
|
JS::PrintContext context { vm, stream, true };
|
||||||
|
MUST(JS::print(value, context));
|
||||||
|
|
||||||
|
return MUST(String::from_stream(stream, stream.used_buffer_size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void DevToolsConsoleClient::handle_result(JS::Value result)
|
void DevToolsConsoleClient::handle_result(JS::Value result)
|
||||||
{
|
{
|
||||||
(void)result;
|
m_client->did_execute_js_console_input(serialize_js_value(m_realm, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DevToolsConsoleClient::report_exception(JS::Error const& exception, bool in_promise)
|
void DevToolsConsoleClient::report_exception(JS::Error const& exception, bool in_promise)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
#include <LibGfx/ShareableBitmap.h>
|
#include <LibGfx/ShareableBitmap.h>
|
||||||
#include <LibJS/Console.h>
|
#include <LibJS/Console.h>
|
||||||
#include <LibJS/Runtime/ConsoleObject.h>
|
#include <LibJS/Runtime/ConsoleObject.h>
|
||||||
|
@ -750,6 +751,11 @@ void PageClient::initialize_js_console(Web::DOM::Document& document)
|
||||||
document.set_console_client(console_client);
|
document.set_console_client(console_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PageClient::did_execute_js_console_input(JsonValue result)
|
||||||
|
{
|
||||||
|
client().async_did_execute_js_console_input(m_id, move(result));
|
||||||
|
}
|
||||||
|
|
||||||
void PageClient::js_console_input(StringView js_source)
|
void PageClient::js_console_input(StringView js_source)
|
||||||
{
|
{
|
||||||
if (m_top_level_document_console_client)
|
if (m_top_level_document_console_client)
|
||||||
|
|
|
@ -85,6 +85,7 @@ public:
|
||||||
|
|
||||||
void initialize_js_console(Web::DOM::Document& document);
|
void initialize_js_console(Web::DOM::Document& document);
|
||||||
void js_console_input(StringView js_source);
|
void js_console_input(StringView js_source);
|
||||||
|
void did_execute_js_console_input(JsonValue);
|
||||||
void run_javascript(StringView js_source);
|
void run_javascript(StringView js_source);
|
||||||
void js_console_request_messages(i32 start_index);
|
void js_console_request_messages(i32 start_index);
|
||||||
void did_output_js_console_message(i32 message_index);
|
void did_output_js_console_message(i32 message_index);
|
||||||
|
|
|
@ -91,6 +91,7 @@ endpoint WebContentClient
|
||||||
|
|
||||||
did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState play_state) =|
|
did_change_audio_play_state(u64 page_id, Web::HTML::AudioPlayState play_state) =|
|
||||||
|
|
||||||
|
did_execute_js_console_input(u64 page_id, JsonValue result) =|
|
||||||
did_output_js_console_message(u64 page_id, i32 message_index) =|
|
did_output_js_console_message(u64 page_id, i32 message_index) =|
|
||||||
did_get_js_console_messages(u64 page_id, i32 start_index, Vector<String> message_types, Vector<String> messages) =|
|
did_get_js_console_messages(u64 page_id, i32 start_index, Vector<String> message_types, Vector<String> messages) =|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue