From 703bd4c9da6a5dac204c202fa9cddb6c38a2fc62 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Sat, 4 Sep 2021 12:12:12 +0100 Subject: Browser: Convert JS ConsoleWidget to new API The console widget now requests messages and receives them in bulk, using the shiny new IPC calls. This lets it display console messages that occurred before the widget was created. :^) --- Userland/Applications/Browser/ConsoleWidget.cpp | 71 ++++++++++++++++++++++--- Userland/Applications/Browser/ConsoleWidget.h | 14 ++++- Userland/Applications/Browser/Tab.cpp | 14 +++-- 3 files changed, 88 insertions(+), 11 deletions(-) (limited to 'Userland/Applications') diff --git a/Userland/Applications/Browser/ConsoleWidget.cpp b/Userland/Applications/Browser/ConsoleWidget.cpp index 500d1dabdb..5c0f961ef7 100644 --- a/Userland/Applications/Browser/ConsoleWidget.cpp +++ b/Userland/Applications/Browser/ConsoleWidget.cpp @@ -1,6 +1,7 @@ /* * Copyright (c) 2020, Hunter Salyer * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -23,6 +24,11 @@ ConsoleWidget::ConsoleWidget() m_output_view = add(); m_output_view->load("data:text/html,"); + // Wait until our output WebView is loaded, and then request any messages that occurred before we existed + m_output_view->on_load_finish = [this](auto&) { + if (on_request_messages) + on_request_messages(0); + }; auto& bottom_container = add(); bottom_container.set_layout(); @@ -65,13 +71,56 @@ ConsoleWidget::~ConsoleWidget() { } -void ConsoleWidget::handle_js_console_output(const String& method, const String& line) +void ConsoleWidget::request_console_messages() { - if (method == "html") { - print_html(line); - } else if (method == "clear") { - clear_output(); + VERIFY(!m_waiting_for_messages); + VERIFY(on_request_messages); + on_request_messages(m_highest_received_message_index + 1); + m_waiting_for_messages = true; +} + +void ConsoleWidget::notify_about_new_console_message(i32 message_index) +{ + if (message_index <= m_highest_received_message_index) { + dbgln("Notified about console message we already have"); + return; + } + if (message_index <= m_highest_notified_message_index) { + dbgln("Notified about console message we're already aware of"); + return; + } + + m_highest_notified_message_index = message_index; + if (!m_waiting_for_messages) + request_console_messages(); +} + +void ConsoleWidget::handle_console_messages(i32 start_index, const Vector& message_types, const Vector& messages) +{ + i32 end_index = start_index + message_types.size() - 1; + if (end_index <= m_highest_received_message_index) { + dbgln("Received old console messages"); + return; } + + for (size_t i = 0; i < message_types.size(); i++) { + auto& type = message_types[i]; + auto& message = messages[i]; + + if (type == "html") { + print_html(message); + } else if (type == "clear") { + clear_output(); + } else { + VERIFY_NOT_REACHED(); + } + } + + m_highest_received_message_index = end_index; + m_waiting_for_messages = false; + + if (m_highest_received_message_index < m_highest_notified_message_index) + request_console_messages(); } void ConsoleWidget::print_source_line(const StringView& source) @@ -97,7 +146,9 @@ void ConsoleWidget::print_html(StringView const& line) document.body.appendChild(p); )~~~"); m_output_view->run_javascript(builder.string_view()); - m_output_view->scroll_to_bottom(); + // FIXME: Make it scroll to the bottom, using `window.scrollTo()` in the JS above. + // We used to call `m_output_view->scroll_to_bottom();` here, but that does not work because + // it runs synchronously, meaning it happens before the HTML is output via IPC above. } void ConsoleWidget::clear_output() @@ -107,4 +158,12 @@ void ConsoleWidget::clear_output() )~~~"); } +void ConsoleWidget::reset() +{ + clear_output(); + m_highest_notified_message_index = -1; + m_highest_received_message_index = -1; + m_waiting_for_messages = false; +} + } diff --git a/Userland/Applications/Browser/ConsoleWidget.h b/Userland/Applications/Browser/ConsoleWidget.h index 0610865aa7..23276bea94 100644 --- a/Userland/Applications/Browser/ConsoleWidget.h +++ b/Userland/Applications/Browser/ConsoleWidget.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2020, Hunter Salyer * Copyright (c) 2021, Andreas Kling + * Copyright (c) 2021, Sam Atkins * * SPDX-License-Identifier: BSD-2-Clause */ @@ -18,18 +19,27 @@ class ConsoleWidget final : public GUI::Widget { public: virtual ~ConsoleWidget(); - void handle_js_console_output(const String& method, const String& line); + void notify_about_new_console_message(i32 message_index); + void handle_console_messages(i32 start_index, Vector const& message_types, Vector const& messages); void print_source_line(const StringView&); void print_html(const StringView&); - void clear_output(); + void reset(); Function on_js_input; + Function on_request_messages; private: ConsoleWidget(); + void request_console_messages(); + void clear_output(); + RefPtr m_input; RefPtr m_output_view; + + i32 m_highest_notified_message_index { -1 }; + i32 m_highest_received_message_index { -1 }; + bool m_waiting_for_messages { false }; }; } diff --git a/Userland/Applications/Browser/Tab.cpp b/Userland/Applications/Browser/Tab.cpp index 13deed226b..4b997720e1 100644 --- a/Userland/Applications/Browser/Tab.cpp +++ b/Userland/Applications/Browser/Tab.cpp @@ -180,7 +180,7 @@ Tab::Tab(BrowserWindow& window) m_dom_inspector_widget->clear_dom_json(); if (m_console_widget) - m_console_widget->clear_output(); + m_console_widget->reset(); }; hooks().on_load_finish = [this](auto&) { @@ -301,9 +301,14 @@ Tab::Tab(BrowserWindow& window) m_dom_inspector_widget->set_dom_node_properties_json(node_id, specified, computed); }; - hooks().on_js_console_output = [this](auto& method, auto& line) { + hooks().on_js_console_new_message = [this](auto message_index) { if (m_console_widget) - m_console_widget->handle_js_console_output(method, line); + m_console_widget->notify_about_new_console_message(message_index); + }; + + hooks().on_get_js_console_messages = [this](auto start_index, auto& message_types, auto& messages) { + if (m_console_widget) + m_console_widget->handle_console_messages(start_index, message_types, messages); }; auto focus_location_box_action = GUI::Action::create( @@ -520,6 +525,9 @@ void Tab::show_console_window() m_console_widget->on_js_input = [this](String const& js_source) { m_web_content_view->js_console_input(js_source); }; + m_console_widget->on_request_messages = [this](i32 start_index) { + m_web_content_view->js_console_request_messages(start_index); + }; m_web_content_view->js_console_initialize(); } -- cgit v1.2.3